123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995 |
- (function (factory) {
- typeof define === 'function' && define.amd ? define(factory) :
- factory();
- }((function () { 'use strict';
- var isArrayLike = function (value) {
- /**
- * isArrayLike([1, 2, 3]) => true
- * isArrayLike(document.body.children) => true
- * isArrayLike('abc') => true
- * isArrayLike(Function) => false
- */
- return value !== null && typeof value !== 'function' && isFinite(value.length);
- };
- var contains = function (arr, value) {
- if (!isArrayLike(arr)) {
- return false;
- }
- return arr.indexOf(value) > -1;
- };
- var filter = function (arr, func) {
- if (!isArrayLike(arr)) {
- return arr;
- }
- var result = [];
- for (var index = 0; index < arr.length; index++) {
- var value = arr[index];
- if (func(value, index)) {
- result.push(value);
- }
- }
- return result;
- };
- /**
- * Flattens `array` a single level deep.
- *
- * @param {Array} arr The array to inspect.
- * @param {Array} values The values to exclude.
- * @return {Array} Returns the new array of filtered values.
- * @example
- * difference([2, 1], [2, 3]); // => [1]
- */
- var difference = function (arr, values) {
- if (values === void 0) { values = []; }
- return filter(arr, function (value) { return !contains(values, value); });
- };
- var toString = {}.toString;
- var isType = function (value, type) { return toString.call(value) === '[object ' + type + ']'; };
- /**
- * 是否为函数
- * @param {*} fn 对象
- * @return {Boolean} 是否函数
- */
- var isFunction = (function (value) {
- return isType(value, 'Function');
- });
- // isFinite,
- var isNil = function (value) {
- /**
- * isNil(null) => true
- * isNil() => true
- */
- return value === null || value === undefined;
- };
- var isArray = (function (value) {
- return Array.isArray ?
- Array.isArray(value) :
- isType(value, 'Array');
- });
- var isObject = (function (value) {
- /**
- * isObject({}) => true
- * isObject([1, 2, 3]) => true
- * isObject(Function) => true
- * isObject(null) => false
- */
- var type = typeof value;
- return value !== null && type === 'object' || type === 'function';
- });
- function each(elements, func) {
- if (!elements) {
- return;
- }
- var rst;
- if (isArray(elements)) {
- for (var i = 0, len = elements.length; i < len; i++) {
- rst = func(elements[i], i);
- if (rst === false) {
- break;
- }
- }
- }
- else if (isObject(elements)) {
- for (var k in elements) {
- if (elements.hasOwnProperty(k)) {
- rst = func(elements[k], k);
- if (rst === false) {
- break;
- }
- }
- }
- }
- }
- var keys = Object.keys ? function (obj) { return Object.keys(obj); } : function (obj) {
- var result = [];
- each(obj, function (value, key) {
- if (!(isFunction(obj) && key === 'prototype')) {
- result.push(key);
- }
- });
- return result;
- };
- function isMatch(obj, attrs) {
- var _keys = keys(attrs);
- var length = _keys.length;
- if (isNil(obj))
- return !length;
- for (var i = 0; i < length; i += 1) {
- var key = _keys[i];
- if (attrs[key] !== obj[key] || !(key in obj)) {
- return false;
- }
- }
- return true;
- }
- var isObjectLike = function (value) {
- /**
- * isObjectLike({}) => true
- * isObjectLike([1, 2, 3]) => true
- * isObjectLike(Function) => false
- * isObjectLike(null) => false
- */
- return typeof value === 'object' && value !== null;
- };
- var isPlainObject = function (value) {
- /**
- * isObjectLike(new Foo) => false
- * isObjectLike([1, 2, 3]) => false
- * isObjectLike({ x: 0, y: 0 }) => true
- * isObjectLike(Object.create(null)) => true
- */
- if (!isObjectLike(value) || !isType(value, 'Object')) {
- return false;
- }
- if (Object.getPrototypeOf(value) === null) {
- return true;
- }
- var proto = value;
- while (Object.getPrototypeOf(proto) !== null) {
- proto = Object.getPrototypeOf(proto);
- }
- return Object.getPrototypeOf(value) === proto;
- };
- function find(arr, predicate) {
- if (!isArray(arr))
- return null;
- var _predicate;
- if (isFunction(predicate)) {
- _predicate = predicate;
- }
- if (isPlainObject(predicate)) {
- _predicate = function (a) { return isMatch(a, predicate); };
- }
- if (_predicate) {
- for (var i = 0; i < arr.length; i += 1) {
- if (_predicate(arr[i])) {
- return arr[i];
- }
- }
- }
- return null;
- }
- function findIndex(arr, predicate, fromIndex) {
- if (fromIndex === void 0) { fromIndex = 0; }
- for (var i = fromIndex; i < arr.length; i++) {
- if (predicate(arr[i], i)) {
- // 找到终止循环
- return i;
- }
- }
- return -1;
- }
- var firstValue = function (data, name) {
- var rst = null;
- for (var i = 0; i < data.length; i++) {
- var obj = data[i];
- var value = obj[name];
- if (!isNil(value)) {
- if (isArray(value)) {
- rst = value[0]; // todo 这里是否应该使用递归,调用 firstValue @绝云
- }
- else {
- rst = value;
- }
- break;
- }
- }
- return rst;
- };
- /**
- * Flattens `array` a single level deep.
- *
- * @param {Array} arr The array to flatten.
- * @return {Array} Returns the new flattened array.
- * @example
- *
- * flatten([1, [2, [3, [4]], 5]]); // => [1, 2, [3, [4]], 5]
- */
- var flatten = function (arr) {
- if (!isArray(arr)) {
- return [];
- }
- var rst = [];
- for (var i = 0; i < arr.length; i++) {
- rst = rst.concat(arr[i]);
- }
- return rst;
- };
- /**
- * Flattens `array` a single level deep.
- *
- * @param {Array} arr The array to flatten.
- * @param {Array} result The array to return.
- * @return {Array} Returns the new flattened array.
- * @example
- *
- * flattenDeep([1, [2, [3, [4]], 5]]); // => [1, 2, 3, 4, 5]
- */
- var flattenDeep = function (arr, result) {
- if (result === void 0) { result = []; }
- if (!isArray(arr)) {
- result.push(arr);
- }
- else {
- for (var i = 0; i < arr.length; i += 1) {
- flattenDeep(arr[i], result);
- }
- }
- return result;
- };
- /**
- * @param {Array} arr The array to iterate over.
- * @return {*} Returns the maximum value.
- * @example
- *
- * max([1, 2]);
- * // => 2
- *
- * max([]);
- * // => undefined
- *
- * const data = new Array(1250010).fill(1).map((d,idx) => idx);
- *
- * max(data);
- * // => 1250010
- * // Math.max(...data) will encounter "Maximum call stack size exceeded" error
- */
- var getMax = (function (arr) {
- if (!isArray(arr)) {
- return undefined;
- }
- return arr.reduce(function (prev, curr) {
- return Math.max(prev, curr);
- }, arr[0]);
- });
- /**
- * @param {Array} arr The array to iterate over.
- * @return {*} Returns the minimum value.
- * @example
- *
- * min([1, 2]);
- * // => 1
- *
- * min([]);
- * // => undefined
- *
- * const data = new Array(1250010).fill(1).map((d,idx) => idx);
- *
- * min(data);
- * // => 1250010
- * // Math.min(...data) will encounter "Maximum call stack size exceeded" error
- */
- var getMin = (function (arr) {
- if (!isArray(arr)) {
- return undefined;
- }
- return arr.reduce(function (prev, curr) {
- return Math.min(prev, curr);
- }, arr[0]);
- });
- var getRange = function (values) {
- // 存在 NaN 时,min,max 判定会出问题
- var filterValues = values.filter(function (v) { return !isNaN(v); });
- if (!filterValues.length) {
- // 如果没有数值则直接返回0
- return {
- min: 0,
- max: 0,
- };
- }
- if (isArray(values[0])) {
- var tmp = [];
- for (var i = 0; i < values.length; i++) {
- tmp = tmp.concat(values[i]);
- }
- filterValues = tmp;
- }
- var max = getMax(filterValues);
- var min = getMin(filterValues);
- return {
- min: min,
- max: max,
- };
- };
- var arrPrototype = Array.prototype;
- var splice = arrPrototype.splice;
- var indexOf = arrPrototype.indexOf;
- var pull = function (arr) {
- var values = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- values[_i - 1] = arguments[_i];
- }
- for (var i = 0; i < values.length; i++) {
- var value = values[i];
- var fromIndex = -1;
- while ((fromIndex = indexOf.call(arr, value)) > -1) {
- splice.call(arr, fromIndex, 1);
- }
- }
- return arr;
- };
- var splice$1 = Array.prototype.splice;
- var pullAt = function pullAt(arr, indexes) {
- if (!isArrayLike(arr)) {
- return [];
- }
- var length = arr ? indexes.length : 0;
- var last = length - 1;
- while (length--) {
- var previous = void 0;
- var index = indexes[length];
- if (length === last || index !== previous) {
- previous = index;
- splice$1.call(arr, index, 1);
- }
- }
- return arr;
- };
- var reduce = function (arr, fn, init) {
- if (!isArray(arr) && !isPlainObject(arr)) {
- return arr;
- }
- var result = init;
- each(arr, function (data, i) {
- result = fn(result, data, i);
- });
- return result;
- };
- var remove = function (arr, predicate) {
- /**
- * const arr = [1, 2, 3, 4]
- * const evens = remove(arr, n => n % 2 == 0)
- * console.log(arr) // => [1, 3]
- * console.log(evens) // => [2, 4]
- */
- var result = [];
- if (!isArrayLike(arr)) {
- return result;
- }
- var i = -1;
- var indexes = [];
- var length = arr.length;
- while (++i < length) {
- var value = arr[i];
- if (predicate(value, i, arr)) {
- result.push(value);
- indexes.push(i);
- }
- }
- pullAt(arr, indexes);
- return result;
- };
- var isString = (function (str) {
- return isType(str, 'String');
- });
- function sortBy(arr, key) {
- var comparer;
- if (isFunction(key)) {
- comparer = function (a, b) { return key(a) - key(b); };
- }
- else {
- var keys_1 = [];
- if (isString(key)) {
- keys_1.push(key);
- }
- else if (isArray(key)) {
- keys_1 = key;
- }
- comparer = function (a, b) {
- for (var i = 0; i < keys_1.length; i += 1) {
- var prop = keys_1[i];
- if (a[prop] > b[prop]) {
- return 1;
- }
- if (a[prop] < b[prop]) {
- return -1;
- }
- }
- return 0;
- };
- }
- arr.sort(comparer);
- return arr;
- }
- function uniq(arr, cache) {
- if (cache === void 0) { cache = new Map(); }
- var r = [];
- if (Array.isArray(arr)) {
- for (var i = 0, len = arr.length; i < len; i++) {
- var item = arr[i];
- // 加一个 cache,提升性能
- if (!cache.has(item)) {
- r.push(item);
- cache.set(item, true);
- }
- }
- }
- return r;
- }
- var union = function () {
- var sources = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- sources[_i] = arguments[_i];
- }
- return uniq([].concat.apply([], sources));
- };
- var valuesOfKey = (function (data, name) {
- var rst = [];
- var tmpMap = {};
- for (var i = 0; i < data.length; i++) {
- var obj = data[i];
- var value = obj[name];
- if (!isNil(value)) {
- // flatten
- if (!isArray(value)) {
- value = [value];
- }
- for (var j = 0; j < value.length; j++) {
- var val = value[j];
- // unique
- if (!tmpMap[val]) {
- rst.push(val);
- tmpMap[val] = true;
- }
- }
- }
- }
- return rst;
- });
- function head(o) {
- if (isArrayLike(o)) {
- return o[0];
- }
- return undefined;
- }
- function last(o) {
- if (isArrayLike(o)) {
- var arr = o;
- return arr[arr.length - 1];
- }
- return undefined;
- }
- function startsWith(arr, e) {
- return (isArray(arr) || isString(arr)) ? arr[0] === e : false;
- }
- function endsWith(arr, e) {
- return (isArray(arr) || isString(arr)) ? arr[arr.length - 1] === e : false;
- }
- /**
- * 只要有一个不满足条件就返回 false
- * @param arr
- * @param func
- */
- var every = function (arr, func) {
- for (var i = 0; i < arr.length; i++) {
- if (!func(arr[i], i))
- return false;
- }
- return true;
- };
- /**
- * 只要有一个满足条件就返回 true
- * @param arr
- * @param func
- */
- var some = function (arr, func) {
- for (var i = 0; i < arr.length; i++) {
- if (func(arr[i], i))
- return true;
- }
- return false;
- };
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- function groupBy(data, condition) {
- if (!condition || !isArray(data)) {
- return {};
- }
- var result = {};
- // 兼容方法和 字符串的写法
- var predicate = isFunction(condition) ? condition : function (item) { return item[condition]; };
- var key;
- for (var i = 0; i < data.length; i++) {
- var item = data[i];
- key = predicate(item);
- if (hasOwnProperty.call(result, key)) {
- result[key].push(item);
- }
- else {
- result[key] = [item];
- }
- }
- return result;
- }
- /**
- * 将数据分组成 map
- * @param data
- * @param condition
- */
- function groupToMap(data, condition) {
- if (!condition) {
- return {
- 0: data,
- };
- }
- if (!isFunction(condition)) {
- // 如果是字符串,则按照 a*b 风格成数组
- var paramscondition_1 = isArray(condition) ? condition : condition.replace(/\s+/g, '').split('*');
- condition = function (row) {
- var unique = '_'; // 避免出现数字作为Key的情况,会进行按照数字的排序
- // 根据字段列表的值,拼接成 key
- for (var i = 0, l = paramscondition_1.length; i < l; i++) {
- unique += row[paramscondition_1[i]] && row[paramscondition_1[i]].toString();
- }
- return unique;
- };
- }
- return groupBy(data, condition);
- }
- var group = (function (data, condition) {
- if (!condition) {
- // 没有条件,则自身改成数组
- return [data];
- }
- var groups = groupToMap(data, condition);
- var array = [];
- for (var i in groups) {
- array.push(groups[i]);
- }
- return array;
- });
- /**
- * 获取封装的事件
- * @protected
- * @param {Object} obj 对象
- * @param {String} action 事件名称
- * @return {Function} 返回事件处理函数
- */
- function getWrapBehavior(obj, action) {
- return obj['_wrap_' + action];
- }
- /**
- * 封装事件,便于使用上下文this,和便于解除事件时使用
- * @protected
- * @param {Object} obj 对象
- * @param {String} action 事件名称
- * @return {Function} 返回事件处理函数
- */
- function wrapBehavior(obj, action) {
- if (obj['_wrap_' + action]) {
- return obj['_wrap_' + action];
- }
- var method = function (e) {
- obj[action](e);
- };
- obj['_wrap_' + action] = method;
- return method;
- }
- var numColorCache = {};
- function numberToColor(num) {
- // 增加缓存
- var color = numColorCache[num];
- if (!color) {
- var str = num.toString(16);
- for (var i = str.length; i < 6; i++) {
- str = '0' + str;
- }
- color = '#' + str;
- numColorCache[num] = color;
- }
- return color;
- }
- function parseRadius(radius) {
- var r1 = 0, r2 = 0, r3 = 0, r4 = 0;
- if (isArray(radius)) {
- if (radius.length === 1) {
- r1 = r2 = r3 = r4 = radius[0];
- }
- else if (radius.length === 2) {
- r1 = r3 = radius[0];
- r2 = r4 = radius[1];
- }
- else if (radius.length === 3) {
- r1 = radius[0];
- r2 = r4 = radius[1];
- r3 = radius[2];
- }
- else {
- r1 = radius[0];
- r2 = radius[1];
- r3 = radius[2];
- r4 = radius[3];
- }
- }
- else {
- r1 = r2 = r3 = r4 = radius;
- }
- return {
- r1: r1,
- r2: r2,
- r3: r3,
- r4: r4
- };
- }
- var clamp = function (a, min, max) {
- if (a < min) {
- return min;
- }
- else if (a > max) {
- return max;
- }
- return a;
- };
- var fixedBase = function (v, base) {
- var str = base.toString();
- var index = str.indexOf('.');
- if (index === -1) {
- return Math.round(v);
- }
- var length = str.substr(index + 1).length;
- if (length > 20) {
- length = 20;
- }
- return parseFloat(v.toFixed(length));
- };
- /**
- * 判断是否数字
- * @return {Boolean} 是否数字
- */
- var isNumber = function (value) {
- return isType(value, 'Number');
- };
- var isDecimal = function (num) {
- return isNumber(num) && num % 1 !== 0;
- };
- var isEven = function (num) {
- return isNumber(num) && num % 2 === 0;
- };
- var isInteger = Number.isInteger ? Number.isInteger : function (num) {
- return isNumber(num) && num % 1 === 0;
- };
- var isNegative = function (num) {
- return isNumber(num) && num < 0;
- };
- var PRECISION = 0.00001; // numbers less than this is considered as 0
- function isNumberEqual(a, b, precision) {
- if (precision === void 0) { precision = PRECISION; }
- return Math.abs((a - b)) < precision;
- }
- var isOdd = function (num) {
- return isNumber(num) && num % 2 !== 0;
- };
- var isPositive = function (num) {
- return isNumber(num) && num > 0;
- };
- /**
- * @param {Array} arr The array to iterate over.
- * @param {Function} [fn] The iteratee invoked per element.
- * @return {*} Returns the maximum value.
- * @example
- *
- * var objects = [{ 'n': 1 }, { 'n': 2 }];
- *
- * maxBy(objects, function(o) { return o.n; });
- * // => { 'n': 2 }
- *
- * maxBy(objects, 'n');
- * // => { 'n': 2 }
- */
- var maxBy = (function (arr, fn) {
- if (!isArray(arr)) {
- return undefined;
- }
- var maxItem;
- var max = -Infinity;
- for (var i = 0; i < arr.length; i++) {
- var item = arr[i];
- var v = isFunction(fn) ? fn(item) : item[fn];
- if (v > max) {
- maxItem = item;
- max = v;
- }
- }
- return maxItem;
- });
- /**
- * @param {Array} arr The array to iterate over.
- * @param {Function} [fn] The iteratee invoked per element.
- * @return {*} Returns the minimum value.
- * @example
- *
- * var objects = [{ 'n': 1 }, { 'n': 2 }];
- *
- * minBy(objects, function(o) { return o.n; });
- * // => { 'n': 1 }
- *
- * minBy(objects, 'n');
- * // => { 'n': 1 }
- */
- var minBy = (function (arr, fn) {
- if (!isArray(arr)) {
- return undefined;
- }
- var minItem;
- var min = Infinity;
- for (var i = 0; i < arr.length; i++) {
- var item = arr[i];
- var v = isFunction(fn) ? fn(item) : item[fn];
- if (v < min) {
- minItem = item;
- min = v;
- }
- }
- return minItem;
- });
- var mod = function (n, m) {
- return ((n % m) + m) % m;
- };
- var DEGREE = 180 / Math.PI;
- var toDegree = function (radian) {
- return DEGREE * radian;
- };
- var RADIAN = Math.PI / 180;
- var toRadian = function (degree) {
- return RADIAN * degree;
- };
- var has = (function (obj, key) { return obj.hasOwnProperty(key); });
- // @ts-ignore
- var values = Object.values ? function (obj) { return Object.values(obj); } : function (obj) {
- var result = [];
- each(obj, function (value, key) {
- if (!(isFunction(obj) && key === 'prototype')) {
- result.push(value);
- }
- });
- return result;
- };
- var hasValue = (function (obj, value) { return contains(values(obj), value); });
- var toString$1 = (function (value) {
- if (isNil(value))
- return '';
- return value.toString();
- });
- var lowerCase = function (str) {
- return toString$1(str).toLowerCase();
- };
- var lowerFirst = function (value) {
- var str = toString$1(value);
- return str.charAt(0).toLowerCase() + str.substring(1);
- };
- function substitute(str, o) {
- if (!str || !o) {
- return str;
- }
- return str.replace(/\\?\{([^{}]+)\}/g, function (match, name) {
- if (match.charAt(0) === '\\') {
- return match.slice(1);
- }
- return (o[name] === undefined) ? '' : o[name];
- });
- }
- var upperCase = function (str) {
- return toString$1(str).toUpperCase();
- };
- var upperFirst = function (value) {
- var str = toString$1(value);
- return str.charAt(0).toUpperCase() + str.substring(1);
- };
- var toString$2 = {}.toString;
- var getType = function (value) {
- return toString$2.call(value).replace(/^\[object /, '').replace(/]$/, '');
- };
- /**
- * 是否是参数类型
- *
- * @param {Object} value 测试的值
- * @return {Boolean}
- */
- var isArguments = function (value) {
- return isType(value, 'Arguments');
- };
- /**
- * 是否是布尔类型
- *
- * @param {Object} value 测试的值
- * @return {Boolean}
- */
- var isBoolean = function (value) {
- return isType(value, 'Boolean');
- };
- var isDate = function (value) {
- return isType(value, 'Date');
- };
- /**
- * 是否是参数类型
- *
- * @param {Object} value 测试的值
- * @return {Boolean}
- */
- var isError = function (value) {
- return isType(value, 'Error');
- };
- /**
- * 判断是否为有限数
- * @return {Boolean}
- */
- function _isFinite (value) {
- return isNumber(value) && isFinite(value);
- }
- var isNull = function (value) {
- return value === null;
- };
- var objectProto = Object.prototype;
- var isPrototype = function (value) {
- var Ctor = value && value.constructor;
- var proto = (typeof Ctor === 'function' && Ctor.prototype) || objectProto;
- return value === proto;
- };
- var isRegExp = function (str) {
- return isType(str, 'RegExp');
- };
- var isUndefined = function (value) {
- return value === undefined;
- };
- /**
- * 判断是否HTML元素
- * @return {Boolean} 是否HTML元素
- */
- var isElement = function (o) {
- return o instanceof Element || o instanceof HTMLDocument;
- };
- function requestAnimationFrame(fn) {
- var method = window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- // @ts-ignore
- window.mozRequestAnimationFrame ||
- // @ts-ignore
- window.msRequestAnimationFrame ||
- function (f) {
- return setTimeout(f, 16);
- };
- return method(fn);
- }
- function cancelAnimationFrame(handler) {
- var method = window.cancelAnimationFrame ||
- window.webkitCancelAnimationFrame ||
- // @ts-ignore
- window.mozCancelAnimationFrame ||
- // @ts-ignore
- window.msCancelAnimationFrame ||
- clearTimeout;
- method(handler);
- }
- // FIXME: Mutable param should be forbidden in static lang.
- function _mix(dist, obj) {
- for (var key in obj) {
- if (obj.hasOwnProperty(key) && key !== 'constructor' && obj[key] !== undefined) {
- dist[key] = obj[key];
- }
- }
- }
- function mix(dist, src1, src2, src3) {
- if (src1)
- _mix(dist, src1);
- if (src2)
- _mix(dist, src2);
- if (src3)
- _mix(dist, src3);
- return dist;
- }
- var augment = function () {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- var c = args[0];
- for (var i = 1; i < args.length; i++) {
- var obj = args[i];
- if (isFunction(obj)) {
- obj = obj.prototype;
- }
- mix(c.prototype, obj);
- }
- };
- var clone = function (obj) {
- if (typeof obj !== 'object' || obj === null) {
- return obj;
- }
- var rst;
- if (isArray(obj)) {
- rst = [];
- for (var i = 0, l = obj.length; i < l; i++) {
- if (typeof obj[i] === 'object' && obj[i] != null) {
- rst[i] = clone(obj[i]);
- }
- else {
- rst[i] = obj[i];
- }
- }
- }
- else {
- rst = {};
- for (var k in obj) {
- if (typeof obj[k] === 'object' && obj[k] != null) {
- rst[k] = clone(obj[k]);
- }
- else {
- rst[k] = obj[k];
- }
- }
- }
- return rst;
- };
- function debounce(func, wait, immediate) {
- var timeout;
- return function () {
- var context = this, args = arguments;
- var later = function () {
- timeout = null;
- if (!immediate) {
- func.apply(context, args);
- }
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow) {
- func.apply(context, args);
- }
- };
- }
- /**
- * _.memoize(calColor);
- * _.memoize(calColor, (...args) => args[0]);
- * @param f
- * @param resolver
- */
- var memoize = (function (f, resolver) {
- if (!isFunction(f)) {
- throw new TypeError('Expected a function');
- }
- var memoized = function () {
- var args = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- args[_i] = arguments[_i];
- }
- // 使用方法构造 key,如果不存在 resolver,则直接取第一个参数作为 key
- var key = resolver ? resolver.apply(this, args) : args[0];
- var cache = memoized.cache;
- if (cache.has(key)) {
- return cache.get(key);
- }
- var result = f.apply(this, args);
- // 缓存起来
- cache.set(key, result);
- return result;
- };
- memoized.cache = new Map();
- return memoized;
- });
- var MAX_MIX_LEVEL = 5;
- function _deepMix(dist, src, level, maxLevel) {
- level = level || 0;
- maxLevel = maxLevel || MAX_MIX_LEVEL;
- for (var key in src) {
- if (src.hasOwnProperty(key)) {
- var value = src[key];
- if (value !== null && isPlainObject(value)) {
- if (!isPlainObject(dist[key])) {
- dist[key] = {};
- }
- if (level < maxLevel) {
- _deepMix(dist[key], value, level + 1, maxLevel);
- }
- else {
- dist[key] = src[key];
- }
- }
- else if (isArray(value)) {
- dist[key] = [];
- dist[key] = dist[key].concat(value);
- }
- else if (value !== undefined) {
- dist[key] = value;
- }
- }
- }
- }
- // todo 重写
- var deepMix = function (rst) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- for (var i = 0; i < args.length; i += 1) {
- _deepMix(rst, args[i]);
- }
- return rst;
- };
- var extend = function (subclass, superclass, overrides, staticOverrides) {
- // 如果只提供父类构造函数,则自动生成子类构造函数
- if (!isFunction(superclass)) {
- overrides = superclass;
- superclass = subclass;
- subclass = function () { };
- }
- var create = Object.create ?
- function (proto, c) {
- return Object.create(proto, {
- constructor: {
- value: c
- }
- });
- } :
- function (proto, c) {
- function Tmp() { }
- Tmp.prototype = proto;
- var o = new Tmp();
- o.constructor = c;
- return o;
- };
- var superObj = create(superclass.prototype, subclass); // new superclass(),//实例化父类作为子类的prototype
- subclass.prototype = mix(superObj, subclass.prototype); // 指定子类的prototype
- subclass.superclass = create(superclass.prototype, superclass);
- mix(superObj, overrides);
- mix(subclass, staticOverrides);
- return subclass;
- };
- var indexOf$1 = function (arr, obj) {
- if (!isArrayLike(arr)) {
- return -1;
- }
- var m = Array.prototype.indexOf;
- if (m) {
- return m.call(arr, obj);
- }
- var index = -1;
- for (var i = 0; i < arr.length; i++) {
- if (arr[i] === obj) {
- index = i;
- break;
- }
- }
- return index;
- };
- var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
- function isEmpty(value) {
- /**
- * isEmpty(null) => true
- * isEmpty() => true
- * isEmpty(true) => true
- * isEmpty(1) => true
- * isEmpty([1, 2, 3]) => false
- * isEmpty('abc') => false
- * isEmpty({ a: 1 }) => false
- */
- if (isNil(value)) {
- return true;
- }
- if (isArrayLike(value)) {
- return !value.length;
- }
- var type = getType(value);
- if (type === 'Map' || type === 'Set') {
- return !value.size;
- }
- if (isPrototype(value)) {
- return !Object.keys(value).length;
- }
- for (var key in value) {
- if (hasOwnProperty$1.call(value, key)) {
- return false;
- }
- }
- return true;
- }
- var isEqual = function (value, other) {
- if (value === other) {
- return true;
- }
- if (!value || !other) {
- return false;
- }
- if (isString(value) || isString(other)) {
- return false;
- }
- if (isArrayLike(value) || isArrayLike(other)) {
- if (value.length !== other.length) {
- return false;
- }
- var rst = true;
- for (var i = 0; i < value.length; i++) {
- rst = isEqual(value[i], other[i]);
- if (!rst) {
- break;
- }
- }
- return rst;
- }
- if (isObjectLike(value) || isObjectLike(other)) {
- var valueKeys = Object.keys(value);
- var otherKeys = Object.keys(other);
- if (valueKeys.length !== otherKeys.length) {
- return false;
- }
- var rst = true;
- for (var i = 0; i < valueKeys.length; i++) {
- rst = isEqual(value[valueKeys[i]], other[valueKeys[i]]);
- if (!rst) {
- break;
- }
- }
- return rst;
- }
- return false;
- };
- /**
- * @param {*} value The value to compare.
- * @param {*} other The other value to compare.
- * @param {Function} [fn] The function to customize comparisons.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * function isGreeting(value) {
- * return /^h(?:i|ello)$/.test(value);
- * }
- *
- * function customizer(objValue, othValue) {
- * if (isGreeting(objValue) && isGreeting(othValue)) {
- * return true;
- * }
- * }
- *
- * var array = ['hello', 'goodbye'];
- * var other = ['hi', 'goodbye'];
- *
- * isEqualWith(array, other, customizer); // => true
- */
- var isEqualWith = (function (value, other, fn) {
- if (!isFunction(fn)) {
- return isEqual(value, other);
- }
- return !!fn(value, other);
- });
- var map = function (arr, func) {
- if (!isArrayLike(arr)) {
- // @ts-ignore
- return arr;
- }
- var result = [];
- for (var index = 0; index < arr.length; index++) {
- var value = arr[index];
- result.push(func(value, index));
- }
- return result;
- };
- var identity = function (v) { return v; };
- var mapValues = (function (object, func) {
- if (func === void 0) { func = identity; }
- var r = {};
- if (isObject(object) && !isNil(object)) {
- Object.keys(object).forEach(function (key) {
- // @ts-ignore
- r[key] = func(object[key], key);
- });
- }
- return r;
- });
- /**
- * https://github.com/developit/dlv/blob/master/index.js
- * @param obj
- * @param key
- * @param defaultValue
- */
- var get = (function (obj, key, defaultValue) {
- var p = 0;
- var keyArr = isString(key) ? key.split('.') : key;
- while (obj && p < keyArr.length) {
- obj = obj[keyArr[p++]];
- }
- return (obj === undefined || p < keyArr.length) ? defaultValue : obj;
- });
- /**
- * https://github.com/developit/dlv/blob/master/index.js
- * @param obj
- * @param path
- * @param value
- */
- var set = (function (obj, path, value) {
- var o = obj;
- var keyArr = isString(path) ? path.split('.') : path;
- keyArr.forEach(function (key, idx) {
- // 不是最后一个
- if (idx < keyArr.length - 1) {
- if (!isObject(o[key])) {
- o[key] = isNumber(keyArr[idx + 1]) ? [] : {};
- }
- o = o[key];
- }
- else {
- o[key] = value;
- }
- });
- return obj;
- });
- var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
- var pick = (function (object, keys) {
- if (object === null || !isPlainObject(object)) {
- return {};
- }
- var result = {};
- each(keys, function (key) {
- if (hasOwnProperty$2.call(object, key)) {
- result[key] = object[key];
- }
- });
- return result;
- });
- var omit = (function (obj, keys) {
- return reduce(obj, function (r, curr, key) {
- if (!keys.includes(key)) {
- r[key] = curr;
- }
- return r;
- }, {});
- });
- var throttle = (function (func, wait, options) {
- var timeout, context, args, result;
- var previous = 0;
- if (!options)
- options = {};
- var later = function () {
- previous = options.leading === false ? 0 : Date.now();
- timeout = null;
- result = func.apply(context, args);
- if (!timeout)
- context = args = null;
- };
- var throttled = function () {
- var now = Date.now();
- if (!previous && options.leading === false)
- previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0 || remaining > wait) {
- if (timeout) {
- clearTimeout(timeout);
- timeout = null;
- }
- previous = now;
- result = func.apply(context, args);
- if (!timeout)
- context = args = null;
- }
- else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- throttled.cancel = function () {
- clearTimeout(timeout);
- previous = 0;
- timeout = context = args = null;
- };
- return throttled;
- });
- var toArray = (function (value) {
- return isArrayLike(value) ? Array.prototype.slice.call(value) : [];
- });
- var map$1 = {};
- var uniqueId = (function (prefix) {
- prefix = prefix || 'g';
- if (!map$1[prefix]) {
- map$1[prefix] = 1;
- }
- else {
- map$1[prefix] += 1;
- }
- return prefix + map$1[prefix];
- });
- var noop = (function () { });
- var identity$1 = (function (v) { return v; });
- function size(o) {
- if (isNil(o)) {
- return 0;
- }
- if (isArrayLike(o)) {
- return o.length;
- }
- return Object.keys(o).length;
- }
- /*! *****************************************************************************
- Copyright (c) Microsoft Corporation.
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
- ***************************************************************************** */
- /* global Reflect, Promise */
- var extendStatics = function(d, b) {
- extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
- return extendStatics(d, b);
- };
- function __extends(d, b) {
- if (typeof b !== "function" && b !== null)
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
- }
- /** @deprecated */
- function __spreadArrays() {
- for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
- r[k] = a[j];
- return r;
- }
- function __spreadArray(to, from, pack) {
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
- if (ar || !(i in from)) {
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
- ar[i] = from[i];
- }
- }
- return to.concat(ar || Array.prototype.slice.call(from));
- }
- var ctx;
- /**
- * 计算文本的宽度
- */
- var measureTextWidth = memoize(function (text, font) {
- if (font === void 0) { font = {}; }
- var fontSize = font.fontSize, fontFamily = font.fontFamily, fontWeight = font.fontWeight, fontStyle = font.fontStyle, fontVariant = font.fontVariant;
- if (!ctx) {
- ctx = document.createElement('canvas').getContext('2d');
- }
- ctx.font = [fontStyle, fontVariant, fontWeight, fontSize + "px", fontFamily].join(' ');
- return ctx.measureText(isString(text) ? text : '').width;
- }, function (text, font) {
- if (font === void 0) { font = {}; }
- return __spreadArrays([text], values(font)).join('');
- });
- /**
- * 获取文本的 ... 文本。
- * 算法(减少每次 measureText 的长度,measureText 的性能跟字符串时间相关):
- * 1. 先通过 STEP 逐步计算,找到最后一个小于 maxWidth 的字符串
- * 2. 然后对最后这个字符串二分计算
- * @param text 需要计算的文本, 由于历史原因 除了支持string,还支持空值,number和数组等
- * @param maxWidth 最大宽度
- * @param font 字体
- * @param str 要替换的文本
- */
- var getEllipsisText = (function (text, maxWidth, font, str) {
- if (str === void 0) { str = '...'; }
- var STEP = 16; // 每次 16,调参工程师
- var PLACEHOLDER_WIDTH = measureTextWidth(str, font);
- var leftText = !isString(text) ? toString$1(text) : text;
- var leftWidth = maxWidth;
- var r = []; // 最终的分段字符串
- var currentText;
- var currentWidth;
- if (measureTextWidth(text, font) <= maxWidth) {
- return text;
- }
- // 首先通过 step 计算,找出最大的未超出长度的
- // eslint-disable-next-line no-constant-condition
- while (true) {
- // 更新字符串
- currentText = leftText.substr(0, STEP);
- // 计算宽度
- currentWidth = measureTextWidth(currentText, font);
- // 超出剩余宽度,则停止
- if (currentWidth + PLACEHOLDER_WIDTH > leftWidth) {
- if (currentWidth > leftWidth) {
- break;
- }
- }
- r.push(currentText);
- // 没有超出,则计算剩余宽度
- leftWidth -= currentWidth;
- leftText = leftText.substr(STEP);
- // 字符串整体没有超出
- if (!leftText) {
- return r.join('');
- }
- }
- // 最下的最后一个 STEP,使用 1 递增(用二分效果更高)
- // eslint-disable-next-line no-constant-condition
- while (true) {
- // 更新字符串
- currentText = leftText.substr(0, 1);
- // 计算宽度
- currentWidth = measureTextWidth(currentText, font);
- // 超出剩余宽度,则停止
- if (currentWidth + PLACEHOLDER_WIDTH > leftWidth) {
- break;
- }
- r.push(currentText);
- // 没有超出,则计算剩余宽度
- leftWidth -= currentWidth;
- leftText = leftText.substr(1);
- if (!leftText) {
- return r.join('');
- }
- }
- return "" + r.join('') + str;
- });
- /**
- * k-v 存储
- */
- var default_1 = /** @class */ (function () {
- function default_1() {
- this.map = {};
- }
- default_1.prototype.has = function (key) {
- return this.map[key] !== undefined;
- };
- default_1.prototype.get = function (key, def) {
- var v = this.map[key];
- return v === undefined ? def : v;
- };
- default_1.prototype.set = function (key, value) {
- this.map[key] = value;
- };
- default_1.prototype.clear = function () {
- this.map = {};
- };
- default_1.prototype.delete = function (key) {
- delete this.map[key];
- };
- default_1.prototype.size = function () {
- return Object.keys(this.map).length;
- };
- return default_1;
- }());
- // array
- var esm = /*#__PURE__*/Object.freeze({
- __proto__: null,
- contains: contains,
- includes: contains,
- difference: difference,
- find: find,
- findIndex: findIndex,
- firstValue: firstValue,
- flatten: flatten,
- flattenDeep: flattenDeep,
- getRange: getRange,
- pull: pull,
- pullAt: pullAt,
- reduce: reduce,
- remove: remove,
- sortBy: sortBy,
- union: union,
- uniq: uniq,
- valuesOfKey: valuesOfKey,
- head: head,
- last: last,
- startsWith: startsWith,
- endsWith: endsWith,
- filter: filter,
- every: every,
- some: some,
- group: group,
- groupBy: groupBy,
- groupToMap: groupToMap,
- getWrapBehavior: getWrapBehavior,
- wrapBehavior: wrapBehavior,
- number2color: numberToColor,
- parseRadius: parseRadius,
- clamp: clamp,
- fixedBase: fixedBase,
- isDecimal: isDecimal,
- isEven: isEven,
- isInteger: isInteger,
- isNegative: isNegative,
- isNumberEqual: isNumberEqual,
- isOdd: isOdd,
- isPositive: isPositive,
- max: getMax,
- maxBy: maxBy,
- min: getMin,
- minBy: minBy,
- mod: mod,
- toDegree: toDegree,
- toInteger: parseInt,
- toRadian: toRadian,
- forIn: each,
- has: has,
- hasKey: has,
- hasValue: hasValue,
- keys: keys,
- isMatch: isMatch,
- values: values,
- lowerCase: lowerCase,
- lowerFirst: lowerFirst,
- substitute: substitute,
- upperCase: upperCase,
- upperFirst: upperFirst,
- getType: getType,
- isArguments: isArguments,
- isArray: isArray,
- isArrayLike: isArrayLike,
- isBoolean: isBoolean,
- isDate: isDate,
- isError: isError,
- isFunction: isFunction,
- isFinite: _isFinite,
- isNil: isNil,
- isNull: isNull,
- isNumber: isNumber,
- isObject: isObject,
- isObjectLike: isObjectLike,
- isPlainObject: isPlainObject,
- isPrototype: isPrototype,
- isRegExp: isRegExp,
- isString: isString,
- isType: isType,
- isUndefined: isUndefined,
- isElement: isElement,
- requestAnimationFrame: requestAnimationFrame,
- clearAnimationFrame: cancelAnimationFrame,
- augment: augment,
- clone: clone,
- debounce: debounce,
- memoize: memoize,
- deepMix: deepMix,
- each: each,
- extend: extend,
- indexOf: indexOf$1,
- isEmpty: isEmpty,
- isEqual: isEqual,
- isEqualWith: isEqualWith,
- map: map,
- mapValues: mapValues,
- mix: mix,
- assign: mix,
- get: get,
- set: set,
- pick: pick,
- omit: omit,
- throttle: throttle,
- toArray: toArray,
- toString: toString$1,
- uniqueId: uniqueId,
- noop: noop,
- identity: identity$1,
- size: size,
- measureTextWidth: measureTextWidth,
- getEllipsisText: getEllipsisText,
- Cache: default_1
- });
- function merge(dataArray) {
- var rst = [];
- for (var i = 0, len = dataArray.length; i < len; i++) {
- rst = rst.concat(dataArray[i]);
- }
- return rst;
- }
- function values$1(data, name) {
- var rst = [];
- var tmpMap = {};
- for (var i = 0, len = data.length; i < len; i++) {
- var obj = data[i];
- var value = obj[name];
- if (!isNil(value)) {
- if (!isArray(value)) {
- if (!tmpMap[value]) {
- rst.push(value);
- tmpMap[value] = true;
- }
- } else {
- each(value, function (val) {
- if (!tmpMap[val]) {
- rst.push(val);
- tmpMap[val] = true;
- }
- });
- }
- }
- }
- return rst;
- }
- function firstValue$1(data, name) {
- var rst = null;
- for (var i = 0, len = data.length; i < len; i++) {
- var obj = data[i];
- var value = obj[name];
- if (!isNil(value)) {
- if (isArray(value)) {
- rst = value[0];
- } else {
- rst = value;
- }
- break;
- }
- }
- return rst;
- }
- function groupToMap$1(data, fields) {
- if (!fields) {
- return {
- 0: data
- };
- }
- var callback = function callback(row) {
- var unique = '_';
- for (var i = 0, l = fields.length; i < l; i++) {
- unique += row[fields[i]] && row[fields[i]].toString();
- }
- return unique;
- };
- var groups = {};
- for (var i = 0, len = data.length; i < len; i++) {
- var row = data[i];
- var key = callback(row);
- if (groups[key]) {
- groups[key].push(row);
- } else {
- groups[key] = [row];
- }
- }
- return groups;
- }
- function group$1(data, fields) {
- var appendConditions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
- if (!fields) {
- return [data];
- }
- var groups = groupToMap$1(data, fields);
- var array = [];
- if (fields.length === 1 && appendConditions[fields[0]]) {
- var _values = appendConditions[fields[0]];
- each(_values, function (value) {
- value = '_' + value;
- array.push(groups[value]);
- });
- } else {
- for (var i in groups) {
- array.push(groups[i]);
- }
- }
- return array;
- }
- function remove$1(arr, obj) {
- if (!arr) {
- return;
- }
- var index = arr.indexOf(obj);
- if (index !== -1) {
- arr.splice(index, 1);
- }
- }
- function getRange$1(values) {
- if (!values.length) {
- return {
- min: 0,
- max: 0
- };
- }
- var max = Math.max.apply(null, values);
- var min = Math.min.apply(null, values);
- return {
- min,
- max
- };
- }
- var array = /*#__PURE__*/Object.freeze({
- __proto__: null,
- merge: merge,
- values: values$1,
- firstValue: firstValue$1,
- group: group$1,
- groupToMap: groupToMap$1,
- remove: remove$1,
- getRange: getRange$1
- });
- /**
- * Detects support for options object argument in addEventListener.
- * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
- * @private
- */
- var supportsEventListenerOptions = function () {
- var supports = false;
- try {
- var options = Object.defineProperty({}, 'passive', {
- get() {
- supports = true;
- }
- });
- window.addEventListener('e', null, options);
- } catch (e) {// continue regardless of error
- }
- return supports;
- }(); // Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
- // https://github.com/chartjs/Chart.js/issues/4287
- var eventListenerOptions = supportsEventListenerOptions ? {
- passive: true
- } : false;
- /* global wx, my */
- // weixin miniprogram
- var isWx = typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function'; // ant miniprogram
- var isMy = typeof my === 'object' && typeof my.getSystemInfoSync === 'function'; // in node
- var isNode = typeof global && !typeof window; // in browser
- var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.sessionStorage !== 'undefined';
- function isCanvasElement(el) {
- if (!el || typeof el !== 'object') return false;
- if (el.nodeType === 1 && el.nodeName) {
- // HTMLCanvasElement
- return true;
- } // CanvasElement
- return !!el.isCanvasElement;
- }
- function getPixelRatio() {
- return window && window.devicePixelRatio || 1;
- }
- function getStyle(el, property) {
- return el.currentStyle ? el.currentStyle[property] : document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
- }
- function getWidth(el) {
- var width = getStyle(el, 'width');
- if (width === 'auto') {
- width = el.offsetWidth;
- }
- return parseFloat(width);
- }
- function getHeight(el) {
- var height = getStyle(el, 'height');
- if (height === 'auto') {
- height = el.offsetHeight;
- }
- return parseFloat(height);
- }
- function getDomById(id) {
- if (!id) {
- return null;
- }
- return document.getElementById(id);
- }
- function getRelativePosition(point, canvas) {
- var canvasDom = canvas.get('el');
- if (!canvasDom) return point;
- var {
- top,
- right,
- bottom,
- left
- } = canvasDom.getBoundingClientRect();
- var paddingLeft = parseFloat(getStyle(canvasDom, 'padding-left'));
- var paddingTop = parseFloat(getStyle(canvasDom, 'padding-top'));
- var paddingRight = parseFloat(getStyle(canvasDom, 'padding-right'));
- var paddingBottom = parseFloat(getStyle(canvasDom, 'padding-bottom'));
- var width = right - left - paddingLeft - paddingRight;
- var height = bottom - top - paddingTop - paddingBottom;
- var pixelRatio = canvas.get('pixelRatio');
- var mouseX = (point.x - left - paddingLeft) / width * canvasDom.width / pixelRatio;
- var mouseY = (point.y - top - paddingTop) / height * canvasDom.height / pixelRatio;
- return {
- x: mouseX,
- y: mouseY
- };
- }
- function addEventListener(source, type, listener) {
- source.addEventListener(type, listener, eventListenerOptions);
- }
- function removeEventListener(source, type, listener) {
- source.removeEventListener(type, listener, eventListenerOptions);
- }
- function createEventObj(type, chart, x, y, nativeEvent) {
- return {
- type,
- chart,
- native: nativeEvent || null,
- x: x !== undefined ? x : null,
- y: y !== undefined ? y : null
- };
- }
- function createEvent(event, chart) {
- var type = event.type;
- var clientPoint; // 说明是touch相关事件
- if (event.touches) {
- // https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent/changedTouches
- // 这里直接拿changedTouches就可以了,不管是touchstart, touchmove, touchend changedTouches 都是有的
- // 为了以防万一,做个空判断
- var touch = event.changedTouches[0] || {}; // x, y: 相对canvas原点的位置,clientX, clientY 相对于可视窗口的位置
- var {
- x,
- y,
- clientX,
- clientY
- } = touch; // 小程序环境会有x,y,这里就直接返回
- if (x && y) {
- return createEventObj(type, chart, x, y, event);
- }
- clientPoint = {
- x: clientX,
- y: clientY
- };
- } else {
- // mouse相关事件
- clientPoint = {
- x: event.clientX,
- y: event.clientY
- };
- } // 理论上应该是只有有在浏览器环境才会走到这里
- var canvas = chart.get('canvas'); // 通过clientX, clientY 计算x, y
- var point = getRelativePosition(clientPoint, canvas);
- return createEventObj(type, chart, point.x, point.y, event);
- }
- function measureText(text, font, ctx) {
- if (!ctx) {
- ctx = document.createElement('canvas').getContext('2d');
- }
- ctx.font = font || '12px sans-serif';
- return ctx.measureText(text);
- }
- /**
- * @fileOverview Utility for F2
- * @author dxq613 @gmail.com
- * @author sima.zhang1990@gmail.com
- */
- function isObjectValueEqual(a, b) {
- // for vue.js
- a = Object.assign({}, a);
- b = Object.assign({}, b);
- var aProps = Object.getOwnPropertyNames(a);
- var bProps = Object.getOwnPropertyNames(b);
- if (aProps.length !== bProps.length) {
- return false;
- }
- for (var i = 0, len = aProps.length; i < len; i++) {
- var propName = aProps[i];
- if (a[propName] !== b[propName]) {
- return false;
- }
- }
- return true;
- }
- function parsePadding(padding) {
- var top;
- var right;
- var bottom;
- var left;
- if (isNumber(padding) || isString(padding)) {
- top = bottom = left = right = padding;
- } else if (isArray(padding)) {
- top = padding[0];
- right = !isNil(padding[1]) ? padding[1] : padding[0];
- bottom = !isNil(padding[2]) ? padding[2] : padding[0];
- left = !isNil(padding[3]) ? padding[3] : right;
- }
- return [top, right, bottom, left];
- }
- function directionEnabled(mode, dir) {
- if (mode === undefined) {
- return true;
- } else if (typeof mode === 'string') {
- return mode.indexOf(dir) !== -1;
- }
- return false;
- }
- function toTimeStamp(value) {
- if (isString(value)) {
- if (value.indexOf('T') > 0) {
- value = new Date(value).getTime();
- } else {
- // new Date('2010/01/10') 和 new Date('2010-01-10') 的差别在于:
- // 如果仅有年月日时,前者是带有时区的: Fri Jan 10 2020 02:40:13 GMT+0800 (中国标准时间)
- // 后者会格式化成 Sun Jan 10 2010 08:00:00 GMT+0800 (中国标准时间)
- value = new Date(value.replace(/-/gi, '/')).getTime();
- }
- }
- if (isDate(value)) {
- value = value.getTime();
- }
- return value;
- }
- var Util = /*#__PURE__*/Object.freeze({
- __proto__: null,
- Array: array,
- upperFirst: upperFirst,
- lowerFirst: lowerFirst,
- isString: isString,
- isNumber: isNumber,
- isBoolean: isBoolean,
- isFunction: isFunction,
- isDate: isDate,
- isArray: isArray,
- isNil: isNil,
- isObject: isObject,
- isPlainObject: isPlainObject,
- isEqual: isEqual,
- deepMix: deepMix,
- mix: mix,
- each: each,
- uniq: uniq,
- find: find,
- isObjectValueEqual: isObjectValueEqual,
- parsePadding: parsePadding,
- directionEnabled: directionEnabled,
- toTimeStamp: toTimeStamp,
- isWx: isWx,
- isMy: isMy,
- isNode: isNode,
- isBrowser: isBrowser,
- isCanvasElement: isCanvasElement,
- getPixelRatio: getPixelRatio,
- getStyle: getStyle,
- getWidth: getWidth,
- getHeight: getHeight,
- getDomById: getDomById,
- getRelativePosition: getRelativePosition,
- addEventListener: addEventListener,
- removeEventListener: removeEventListener,
- createEvent: createEvent,
- measureText: measureText
- });
- /**
- * @fileOverview default theme
- * @author dxq613@gail.com
- */
- var color1 = '#E8E8E8'; // color of axis-line and axis-grid
- var color2 = '#808080'; // color of axis label
- var defaultAxis = {
- label: {
- fill: color2,
- fontSize: 10
- },
- line: {
- stroke: color1,
- lineWidth: 1
- },
- grid: {
- type: 'line',
- stroke: color1,
- lineWidth: 1,
- lineDash: [2]
- },
- tickLine: null,
- labelOffset: 7.5
- };
- var Theme = {
- fontFamily: '"Helvetica Neue", "San Francisco", Helvetica, Tahoma, Arial, "PingFang SC", "Hiragino Sans GB", "Heiti SC", "Microsoft YaHei", sans-serif',
- defaultColor: '#1890FF',
- pixelRatio: 1,
- padding: 'auto',
- appendPadding: 15,
- colors: ['#1890FF', '#2FC25B', '#FACC14', '#223273', '#8543E0', '#13C2C2', '#3436C7', '#F04864'],
- shapes: {
- line: ['line', 'dash'],
- point: ['circle', 'hollowCircle']
- },
- sizes: [4, 10],
- axis: {
- common: defaultAxis,
- // common axis configuration
- bottom: mix({}, defaultAxis, {
- grid: null
- }),
- left: mix({}, defaultAxis, {
- line: null
- }),
- right: mix({}, defaultAxis, {
- line: null
- }),
- circle: mix({}, defaultAxis, {
- line: null
- }),
- radius: mix({}, defaultAxis, {
- labelOffset: 4
- })
- },
- shape: {
- line: {
- lineWidth: 2,
- lineJoin: 'round',
- lineCap: 'round'
- },
- point: {
- lineWidth: 0,
- size: 3
- },
- area: {
- fillOpacity: 0.1
- }
- },
- _defaultAxis: defaultAxis
- };
- var Global = {
- version: '3.7.8',
- scales: {},
- widthRatio: {
- column: 1 / 2,
- rose: 0.999999,
- multiplePie: 3 / 4
- },
- lineDash: [4, 4]
- };
- Global.setTheme = function (theme) {
- deepMix(Global, theme);
- };
- Global.setTheme(Theme);
- var EVENT_AFTER_INIT = 'afterinit';
- var EVENT_BEFORE_RENDER = 'beforerender';
- var EVENT_AFTER_RENDER = 'afterrender';
- var EVENT_BEFORE_DATA_CHANGE = 'beforedatachange';
- var EVENT_AFTER_DATA_CHANGE = 'afterdatachange';
- var EVENT_AFTER_SIZE_CHANGE = '_aftersizechange';
- var EVENT_AFTER_GEOM_INIT = '_aftergeominit';
- var EVENT_BEFORE_GEOM_DRAW = 'beforegeomdraw';
- var EVENT_AFTER_GEOM_DRAW = 'aftergeomdraw';
- var EVENT_CLEAR = 'clear';
- var EVENT_CLEAR_INNER = 'clearinner';
- var EVENT_REPAINT = 'repaint';
- // 实现简单的事件机制
- class EventEmit {
- constructor() {
- this.__events = {};
- }
- on(type, listener) {
- if (!type || !listener) {
- return;
- }
- var events = this.__events[type] || [];
- events.push(listener);
- this.__events[type] = events;
- }
- emit(type, e) {
- var _this = this;
- if (isObject(type)) {
- e = type;
- type = e && e.type;
- }
- if (!type) {
- return;
- }
- var events = this.__events[type];
- if (!events || !events.length) {
- return;
- }
- events.forEach(function (listener) {
- listener.call(_this, e);
- });
- }
- off(type, listener) {
- var __events = this.__events;
- var events = __events[type];
- if (!events || !events.length) {
- return;
- } // 如果没有指定方法,则删除所有项
- if (!listener) {
- delete __events[type];
- return;
- } // 删除指定的 listener
- for (var i = 0, len = events.length; i < len; i++) {
- if (events[i] === listener) {
- events.splice(i, 1);
- i--;
- }
- }
- }
- }
- /**
- * @fileOverview Base class of chart and geometry
- * @author dxq613@gmail.com
- */
- class Base extends EventEmit {
- getDefaultCfg() {
- return {};
- }
- constructor(cfg) {
- super();
- var attrs = {};
- var defaultCfg = this.getDefaultCfg();
- this._attrs = attrs;
- mix(attrs, defaultCfg, cfg);
- }
- get(name) {
- return this._attrs[name];
- }
- set(name, value) {
- this._attrs[name] = value;
- }
- destroy() {
- this._attrs = {};
- this.destroyed = true;
- }
- }
- class Plot {
- constructor(cfg) {
- mix(this, cfg);
- this._init();
- }
- _init() {
- var self = this;
- var start = self.start;
- var end = self.end;
- var xMin = Math.min(start.x, end.x);
- var xMax = Math.max(start.x, end.x);
- var yMin = Math.min(start.y, end.y);
- var yMax = Math.max(start.y, end.y);
- this.tl = {
- x: xMin,
- y: yMin
- };
- this.tr = {
- x: xMax,
- y: yMin
- };
- this.bl = {
- x: xMin,
- y: yMax
- };
- this.br = {
- x: xMax,
- y: yMax
- };
- this.width = xMax - xMin;
- this.height = yMax - yMin;
- }
- /**
- * reset
- * @param {Object} start start point
- * @param {Object} end end point
- */
- reset(start, end) {
- this.start = start;
- this.end = end;
- this._init();
- }
- /**
- * check the point is in the range of plot
- * @param {Number} x x value
- * @param {[type]} y y value
- * @return {Boolean} return the result
- */
- isInRange(x, y) {
- if (isObject(x)) {
- y = x.y;
- x = x.x;
- }
- var tl = this.tl;
- var br = this.br;
- return tl.x <= x && x <= br.x && tl.y <= y && y <= br.y;
- }
- }
- var Matrix = {
- generateDefault() {
- return [1, 0, 0, 1, 0, 0];
- },
- isChanged(m) {
- return m[0] !== 1 || m[1] !== 0 || m[2] !== 0 || m[3] !== 1 || m[4] !== 0 || m[5] !== 0;
- },
- multiply(m1, m2) {
- var m11 = m1[0] * m2[0] + m1[2] * m2[1];
- var m12 = m1[1] * m2[0] + m1[3] * m2[1];
- var m21 = m1[0] * m2[2] + m1[2] * m2[3];
- var m22 = m1[1] * m2[2] + m1[3] * m2[3];
- var dx = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
- var dy = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
- return [m11, m12, m21, m22, dx, dy];
- },
- scale(out, m, v) {
- out[0] = m[0] * v[0];
- out[1] = m[1] * v[0];
- out[2] = m[2] * v[1];
- out[3] = m[3] * v[1];
- out[4] = m[4];
- out[5] = m[5];
- return out;
- },
- rotate(out, m, radian) {
- var c = Math.cos(radian);
- var s = Math.sin(radian);
- var m11 = m[0] * c + m[2] * s;
- var m12 = m[1] * c + m[3] * s;
- var m21 = m[0] * -s + m[2] * c;
- var m22 = m[1] * -s + m[3] * c;
- out[0] = m11;
- out[1] = m12;
- out[2] = m21;
- out[3] = m22;
- out[4] = m[4];
- out[5] = m[5];
- return out;
- },
- translate(out, m, v) {
- out[0] = m[0];
- out[1] = m[1];
- out[2] = m[2];
- out[3] = m[3];
- out[4] = m[4] + m[0] * v[0] + m[2] * v[1];
- out[5] = m[5] + m[1] * v[0] + m[3] * v[1];
- return out;
- },
- transform(m, actions) {
- var out = [].concat(m);
- for (var i = 0, len = actions.length; i < len; i++) {
- var action = actions[i];
- switch (action[0]) {
- case 't':
- Matrix.translate(out, out, [action[1], action[2]]);
- break;
- case 's':
- Matrix.scale(out, out, [action[1], action[2]]);
- break;
- case 'r':
- Matrix.rotate(out, out, action[1]);
- break;
- }
- }
- return out;
- }
- };
- /**
- * 2 Dimensional Vector
- * @module vector2
- */
- var Vector2 = {
- /**
- * Creates a new, empty vector2
- *
- * @return {vector2} a new 2D vector
- */
- create() {
- return [0, 0];
- },
- /**
- * Calculates the length of a vector2
- *
- * @param {vector2} v vector to calculate length of
- * @return {Number} length of v
- */
- length(v) {
- var x = v[0];
- var y = v[1];
- return Math.sqrt(x * x + y * y);
- },
- /**
- * Normalize a vector2
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v vector to normalize
- * @return {vector2} out
- */
- normalize(out, v) {
- var len = this.length(v);
- if (len === 0) {
- out[0] = 0;
- out[1] = 0;
- } else {
- out[0] = v[0] / len;
- out[1] = v[1] / len;
- }
- return out;
- },
- /**
- * Adds two vector2's
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- add(out, v1, v2) {
- out[0] = v1[0] + v2[0];
- out[1] = v1[1] + v2[1];
- return out;
- },
- /**
- * Subtracts vector v2 from vector v1
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- sub(out, v1, v2) {
- out[0] = v1[0] - v2[0];
- out[1] = v1[1] - v2[1];
- return out;
- },
- /**
- * Scales a vector2 by a scalar number
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v the vector to scale
- * @param {Number} s amount to scale the vector by
- * @return {vector2} out
- */
- scale(out, v, s) {
- out[0] = v[0] * s;
- out[1] = v[1] * s;
- return out;
- },
- /**
- * Calculates the dot product of two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Number} dot product of v1 and v2
- */
- dot(v1, v2) {
- return v1[0] * v2[0] + v1[1] * v2[1];
- },
- /**
- * Calculates the direction of two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Boolean} the direction of v1 and v2
- */
- direction(v1, v2) {
- return v1[0] * v2[1] - v2[0] * v1[1];
- },
- /**
- * Calculates the angle of two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Number} angle of v1 and v2
- */
- angle(v1, v2) {
- var theta = this.dot(v1, v2) / (this.length(v1) * this.length(v2));
- return Math.acos(theta);
- },
- /**
- * Calculates the angle of two vector2's with direction
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @param {Boolean} direction the direction of two vector2's
- * @return {Number} angle of v1 and v2
- */
- angleTo(v1, v2, direction) {
- var angle = this.angle(v1, v2);
- var angleLargeThanPI = this.direction(v1, v2) >= 0;
- if (direction) {
- if (angleLargeThanPI) {
- return Math.PI * 2 - angle;
- }
- return angle;
- }
- if (angleLargeThanPI) {
- return angle;
- }
- return Math.PI * 2 - angle;
- },
- /**
- * whether a vector2 is zero vector
- *
- * @param {vector2} v vector to calculate
- * @return {Boolean} is or not a zero vector
- */
- zero(v) {
- return v[0] === 0 && v[1] === 0;
- },
- /**
- * Calculates the euclidian distance between two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Number} distance between a and b
- */
- distance(v1, v2) {
- var x = v2[0] - v1[0];
- var y = v2[1] - v1[1];
- return Math.sqrt(x * x + y * y);
- },
- /**
- * Creates a new vector2 initialized with values from an existing vector
- *
- * @param {vector2} v vector to clone
- * @return {Array} a new 2D vector
- */
- clone(v) {
- return [v[0], v[1]];
- },
- /**
- * Return the minimum of two vector2's
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- min(out, v1, v2) {
- out[0] = Math.min(v1[0], v2[0]);
- out[1] = Math.min(v1[1], v2[1]);
- return out;
- },
- /**
- * Return the maximum of two vector2's
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- max(out, v1, v2) {
- out[0] = Math.max(v1[0], v2[0]);
- out[1] = Math.max(v1[1], v2[1]);
- return out;
- },
- /**
- * Transforms the vector2 with a mat2d
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v the vector to transform
- * @param {mat2d} m matrix to transform with
- * @return {vector2} out
- */
- transformMat2d(out, v, m) {
- var x = v[0];
- var y = v[1];
- out[0] = m[0] * x + m[2] * y + m[4];
- out[1] = m[1] * x + m[3] * y + m[5];
- return out;
- }
- };
- var defaultMatrix = [1, 0, 0, 1, 0, 0];
- class Base$1 {
- _initDefaultCfg() {}
- constructor(cfg) {
- this._initDefaultCfg();
- mix(this, cfg);
- var start;
- var end;
- if (this.plot) {
- start = this.plot.bl;
- end = this.plot.tr;
- this.start = start;
- this.end = end;
- } else {
- start = this.start;
- end = this.end;
- }
- this.init(start, end);
- }
- _scale(s1, s2) {
- var matrix = this.matrix;
- var center = this.center;
- Matrix.translate(matrix, matrix, [center.x, center.y]);
- Matrix.scale(matrix, matrix, [s1, s2]);
- Matrix.translate(matrix, matrix, [-center.x, -center.y]);
- }
- init(start, end) {
- this.matrix = [].concat(defaultMatrix); // 设置中心点
- this.center = {
- x: (end.x - start.x) / 2 + start.x,
- y: (end.y - start.y) / 2 + start.y
- };
- if (this.scale) {
- this._scale(this.scale[0], this.scale[1]);
- }
- }
- convertPoint(point) {
- var {
- x,
- y
- } = this._convertPoint(point);
- if (!Matrix.isChanged(this.matrix)) {
- return {
- x,
- y
- };
- }
- var vector = [x, y];
- Vector2.transformMat2d(vector, vector, this.matrix);
- return {
- x: vector[0],
- y: vector[1]
- };
- }
- invertPoint(point) {
- return this._invertPoint(point);
- }
- _convertPoint(point) {
- return point;
- }
- _invertPoint(point) {
- return point;
- }
- reset(plot) {
- this.plot = plot;
- var {
- bl,
- tr
- } = plot;
- this.start = bl;
- this.end = tr;
- this.init(bl, tr);
- }
- }
- class Cartesian extends Base$1 {
- _initDefaultCfg() {
- this.type = 'cartesian';
- this.transposed = false;
- this.isRect = true;
- }
- init(start, end) {
- super.init(start, end);
- this.x = {
- start: start.x,
- end: end.x
- };
- this.y = {
- start: start.y,
- end: end.y
- };
- }
- _convertPoint(point) {
- var self = this;
- var transposed = self.transposed;
- var xDim = transposed ? 'y' : 'x';
- var yDim = transposed ? 'x' : 'y';
- var x = self.x;
- var y = self.y;
- return {
- x: x.start + (x.end - x.start) * point[xDim],
- y: y.start + (y.end - y.start) * point[yDim]
- };
- }
- _invertPoint(point) {
- var self = this;
- var transposed = self.transposed;
- var xDim = transposed ? 'y' : 'x';
- var yDim = transposed ? 'x' : 'y';
- var x = self.x;
- var y = self.y;
- var rst = {};
- rst[xDim] = (point.x - x.start) / (x.end - x.start);
- rst[yDim] = (point.y - y.start) / (y.end - y.start);
- return rst;
- }
- }
- Base$1.Cartesian = Cartesian;
- Base$1.Rect = Cartesian;
- /**
- * @fileOverview the Attribute base class
- */
- function toScaleString(scale, value) {
- if (isString(value)) {
- return value;
- }
- return scale.invert(scale.scale(value));
- }
- /**
- * 所有视觉通道属性的基类
- * @class Attr
- */
- class AttributeBase {
- constructor(cfg) {
- var _this = this;
- /**
- * 属性的类型
- * @type {String}
- */
- this.type = 'base';
- /**
- * 属性的名称
- * @type {String}
- */
- this.name = null;
- /**
- * 回调函数
- * @type {Function}
- */
- this.method = null;
- /**
- * 备选的值数组
- * @type {Array}
- */
- this.values = [];
- /**
- * 属性内部的度量
- * @type {Array}
- */
- this.scales = [];
- /**
- * 是否通过线性取值, 如果未指定,则根据数值的类型判定
- * @type {Boolean}
- */
- this.linear = null;
- /**
- * 当用户设置的 callback 返回 null 时, 应该返回默认 callback 中的值
- */
- var mixedCallback = null;
- var defaultCallback = this.callback;
- if (cfg.callback) {
- var userCallback = cfg.callback;
- mixedCallback = function mixedCallback() {
- for (var _len = arguments.length, params = new Array(_len), _key = 0; _key < _len; _key++) {
- params[_key] = arguments[_key];
- }
- var ret = userCallback(...params);
- if (isNil(ret)) {
- ret = defaultCallback.apply(_this, params);
- }
- return ret;
- };
- }
- mix(this, cfg);
- if (mixedCallback) {
- mix(this, {
- callback: mixedCallback
- });
- }
- } // 获取属性值,将值映射到视觉通道
- _getAttrValue(scale, value) {
- var values = this.values;
- if (scale.isCategory && !this.linear) {
- var index = scale.translate(value);
- return values[index % values.length];
- }
- var percent = scale.scale(value);
- return this.getLinearValue(percent);
- }
- /**
- * 如果进行线性映射,返回对应的映射值
- * @protected
- * @param {Number} percent 百分比
- * @return {*} 颜色值、形状、大小等
- */
- getLinearValue(percent) {
- var values = this.values;
- var steps = values.length - 1;
- var step = Math.floor(steps * percent);
- var leftPercent = steps * percent - step;
- var start = values[step];
- var end = step === steps ? start : values[step + 1];
- var rstValue = start + (end - start) * leftPercent;
- return rstValue;
- }
- /**
- * 默认的回调函数
- * @param {*} value 回调函数的值
- * @type {Function}
- * @return {Array} 返回映射后的值
- */
- callback(value) {
- var self = this;
- var scale = self.scales[0];
- var rstValue = null;
- if (scale.type === 'identity') {
- rstValue = scale.value;
- } else {
- rstValue = self._getAttrValue(scale, value);
- }
- return rstValue;
- }
- /**
- * 根据度量获取属性名
- * @return {Array} dims of this Attribute
- */
- getNames() {
- var scales = this.scales;
- var names = this.names;
- var length = Math.min(scales.length, names.length);
- var rst = [];
- for (var i = 0; i < length; i++) {
- rst.push(names[i]);
- }
- return rst;
- }
- /**
- * 根据度量获取维度名
- * @return {Array} dims of this Attribute
- */
- getFields() {
- var scales = this.scales;
- var rst = [];
- each(scales, function (scale) {
- rst.push(scale.field);
- });
- return rst;
- }
- /**
- * 根据名称获取度量
- * @param {String} name the name of scale
- * @return {Scale} scale
- */
- getScale(name) {
- var scales = this.scales;
- var names = this.names;
- var index = names.indexOf(name);
- return scales[index];
- }
- /**
- * 映射数据
- * @param {*} param1...paramn 多个数值
- * @return {Array} 映射的值组成的数组
- */
- mapping() {
- var scales = this.scales;
- var callback = this.callback;
- for (var _len2 = arguments.length, params = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
- params[_key2] = arguments[_key2];
- }
- var values = params;
- if (callback) {
- for (var i = 0, len = params.length; i < len; i++) {
- params[i] = this._toOriginParam(params[i], scales[i]);
- }
- values = callback.apply(this, params);
- }
- values = [].concat(values);
- return values;
- } // 原始的参数
- _toOriginParam(param, scale) {
- var rst = param;
- if (!scale.isLinear) {
- if (isArray(param)) {
- rst = [];
- for (var i = 0, len = param.length; i < len; i++) {
- rst.push(toScaleString(scale, param[i]));
- }
- } else {
- rst = toScaleString(scale, param);
- }
- }
- return rst;
- }
- }
- class Position extends AttributeBase {
- constructor(cfg) {
- super(cfg);
- this.names = ['x', 'y'];
- this.type = 'position';
- }
- mapping(x, y) {
- var scales = this.scales;
- var coord = this.coord;
- var scaleX = scales[0];
- var scaleY = scales[1];
- var rstX;
- var rstY;
- var obj;
- if (isNil(x) || isNil(y)) {
- return [];
- }
- if (isArray(y) && isArray(x)) {
- rstX = [];
- rstY = [];
- for (var i = 0, j = 0, xLen = x.length, yLen = y.length; i < xLen && j < yLen; i++, j++) {
- obj = coord.convertPoint({
- x: scaleX.scale(x[i]),
- y: scaleY.scale(y[j])
- });
- rstX.push(obj.x);
- rstY.push(obj.y);
- }
- } else if (isArray(y)) {
- x = scaleX.scale(x);
- rstY = [];
- each(y, function (yVal) {
- yVal = scaleY.scale(yVal);
- obj = coord.convertPoint({
- x,
- y: yVal
- });
- if (rstX && rstX !== obj.x) {
- if (!isArray(rstX)) {
- rstX = [rstX];
- }
- rstX.push(obj.x);
- } else {
- rstX = obj.x;
- }
- rstY.push(obj.y);
- });
- } else if (isArray(x)) {
- y = scaleY.scale(y);
- rstX = [];
- each(x, function (xVal) {
- xVal = scaleX.scale(xVal);
- obj = coord.convertPoint({
- x: xVal,
- y
- });
- if (rstY && rstY !== obj.y) {
- if (!isArray(rstY)) {
- rstY = [rstY];
- }
- rstY.push(obj.y);
- } else {
- rstY = obj.y;
- }
- rstX.push(obj.x);
- });
- } else {
- x = scaleX.scale(x);
- y = scaleY.scale(y);
- var point = coord.convertPoint({
- x,
- y
- });
- rstX = point.x;
- rstY = point.y;
- }
- return [rstX, rstY];
- }
- }
- class Shape extends AttributeBase {
- constructor(cfg) {
- super(cfg);
- this.names = ['shape'];
- this.type = 'shape';
- this.gradient = null;
- }
- /**
- * @override
- */
- getLinearValue(percent) {
- var values = this.values;
- var index = Math.round((values.length - 1) * percent);
- return values[index];
- }
- }
- class Size extends AttributeBase {
- constructor(cfg) {
- super(cfg);
- this.names = ['size'];
- this.type = 'size';
- this.gradient = null;
- }
- }
- function getValue(start, end, percent, index) {
- var value = start[index] + (end[index] - start[index]) * percent;
- return value;
- } // convert to hex
- function arr2hex(arr) {
- return '#' + toRGBValue(arr[0]) + toRGBValue(arr[1]) + toRGBValue(arr[2]);
- }
- function toRGBValue(value) {
- value = Math.round(value);
- value = value.toString(16);
- if (value.length === 1) {
- value = '0' + value;
- }
- return value;
- }
- function calColor(colors, percent) {
- var steps = colors.length - 1;
- var step = Math.floor(steps * percent);
- var left = steps * percent - step;
- var start = colors[step];
- var end = step === steps ? start : colors[step + 1];
- var rgb = arr2hex([getValue(start, end, left, 0), getValue(start, end, left, 1), getValue(start, end, left, 2)]);
- return rgb;
- }
- function hex2arr(str) {
- var arr = [];
- arr.push(parseInt(str.substr(1, 2), 16));
- arr.push(parseInt(str.substr(3, 2), 16));
- arr.push(parseInt(str.substr(5, 2), 16));
- return arr;
- }
- var colorCache = {
- black: '#000000',
- blue: '#0000ff',
- grey: '#808080',
- green: '#008000',
- orange: '#ffa500',
- pink: '#ffc0cb',
- purple: '#800080',
- red: '#ff0000',
- white: '#ffffff',
- yellow: '#ffff00'
- };
- /**
- * Returns a hexadecimal string representing this color in RGB space, such as #f7eaba.
- * @param {String} color color value
- * @return {String} Returns a hexadecimal string
- */
- function toHex(color) {
- if (colorCache[color]) {
- return colorCache[color];
- }
- if (color[0] === '#') {
- if (color.length === 7) {
- return color;
- }
- var hex = color.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, function (m, r, g, b) {
- return '#' + r + r + g + g + b + b;
- }); // hex3 to hex6
- colorCache[color] = hex;
- return hex;
- } // rgb/rgba to hex
- var rst = color.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
- rst.shift();
- rst = arr2hex(rst);
- colorCache[color] = rst;
- return rst;
- }
- /**
- * handle the gradient color
- * @param {Array} colors the colors
- * @return {String} return the color value
- */
- function gradient(colors) {
- var points = [];
- if (isString(colors)) {
- colors = colors.split('-');
- }
- each(colors, function (color) {
- if (color.indexOf('#') === -1) {
- color = toHex(color);
- }
- points.push(hex2arr(color));
- });
- return function (percent) {
- return calColor(points, percent);
- };
- }
- class Color extends AttributeBase {
- constructor(cfg) {
- super(cfg);
- this.names = ['color'];
- this.type = 'color';
- this.gradient = null;
- if (isString(this.values)) {
- this.linear = true;
- }
- }
- /**
- * @override
- */
- getLinearValue(percent) {
- var gradient$1 = this.gradient;
- if (!gradient$1) {
- var values = this.values;
- gradient$1 = gradient(values);
- this.gradient = gradient$1;
- }
- return gradient$1(percent);
- }
- }
- var Attr = /*#__PURE__*/Object.freeze({
- __proto__: null,
- Position: Position,
- Shape: Shape,
- Size: Size,
- Color: Color
- });
- var Shape$1 = {};
- var ShapeBase = {
- _coord: null,
- /**
- * draw the shape
- * @param {Object} cfg options
- * @param {Object} container container to store the shapes
- */
- draw(cfg, container) {
- if (this.drawShape) {
- this.drawShape(cfg, container);
- }
- },
- /**
- * set the coordinate instance
- * @param {Coord} coord coordinate instance
- */
- setCoord(coord) {
- this._coord = coord;
- },
- /**
- * convert the normalized value to the canvas position
- * @param {point} point the point to convert
- * @return {point} point return the result
- */
- parsePoint(point) {
- var coord = this._coord;
- if (coord.isPolar) {
- if (point.x === 1) point.x = 0.9999999;
- if (point.y === 1) point.y = 0.9999999;
- }
- return coord.convertPoint(point);
- },
- /**
- * convert the normalized value to the canvas position
- * @param {points} points the array that store the points
- * @return {points} points return the result
- */
- parsePoints(points) {
- if (!points) return false;
- var self = this;
- var rst = [];
- points.forEach(function (point) {
- rst.push(self.parsePoint(point));
- });
- return rst;
- }
- };
- var ShapeFactoryBase = {
- defaultShapeType: null,
- setCoord(coord) {
- this._coord = coord;
- },
- getShape(type) {
- var self = this;
- if (isArray(type)) {
- type = type[0];
- }
- var shape = self[type] || self[self.defaultShapeType];
- shape._coord = self._coord;
- return shape;
- },
- getShapePoints(type, cfg) {
- var shape = this.getShape(type);
- var fn = shape.getPoints || shape.getShapePoints || this.getDefaultPoints;
- var points = fn(cfg);
- return points;
- },
- getDefaultPoints()
- /* cfg */
- {
- return [];
- },
- drawShape(type, cfg, container) {
- var shape = this.getShape(type);
- if (!cfg.color) {
- cfg.color = Global.colors[0];
- }
- return shape.draw(cfg, container);
- }
- };
- Shape$1.registerFactory = function (factoryName, cfg) {
- var className = upperFirst(factoryName);
- var geomObj = mix({}, ShapeFactoryBase, cfg);
- Shape$1[className] = geomObj;
- geomObj.name = factoryName;
- return geomObj;
- };
- Shape$1.registerShape = function (factoryName, shapeType, cfg) {
- var className = upperFirst(factoryName);
- var factory = Shape$1[className];
- var shapeObj = mix({}, ShapeBase, cfg);
- factory[shapeType] = shapeObj;
- return shapeObj;
- };
- Shape$1.registShape = Shape$1.registerShape;
- Shape$1.getShapeFactory = function (factoryName) {
- var self = this;
- factoryName = factoryName || 'point';
- var className = upperFirst(factoryName);
- return self[className];
- };
- function _mix$1(dist, obj) {
- for (var key in obj) {
- if (obj.hasOwnProperty(key) && key !== 'constructor' && obj[key] !== undefined) {
- dist[key] = obj[key];
- }
- }
- }
- var mix$1 = function mix(dist, src1, src2, src3) {
- if (src1) _mix$1(dist, src1);
- if (src2) _mix$1(dist, src2);
- if (src3) _mix$1(dist, src3);
- return dist;
- };
- var mix_1 = mix$1;
- var Adjust =
- /*#__PURE__*/
- function () {
- var _proto = Adjust.prototype;
- _proto._initDefaultCfg = function _initDefaultCfg() {
- this.adjustNames = ['x', 'y']; // 调整的维度,默认,x,y都做调整
- };
- function Adjust(cfg) {
- this._initDefaultCfg();
- mix_1(this, cfg);
- }
- /**
- * @override
- */
- _proto.processAdjust = function processAdjust()
- /* dataArray */
- {};
- return Adjust;
- }();
- var base = Adjust;
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- var GROUP_ATTRS = ['color', 'size', 'shape'];
- var FIELD_ORIGIN = '_origin';
- var FIELD_ORIGIN_Y = '_originY';
- function parseFields(field) {
- if (isArray(field)) {
- return field;
- }
- if (isString(field)) {
- return field.split('*');
- }
- return [field];
- }
- /**
- * The parent class for Geometry
- * @class Geom
- */
- class Geom extends Base {
- getDefaultCfg() {
- return {
- /**
- * geometry type
- * @type {String}
- */
- type: null,
- /**
- * the data of geometry
- * @type {Array}
- */
- data: null,
- /**
- * the attrs of geo,etry
- * @type {Object}
- */
- attrs: {},
- scales: {},
- /**
- * group for storing the shapes
- * @type {Canvas}
- */
- container: null,
- /**
- * style options
- * @type {Object}
- */
- styleOptions: null,
- chart: null,
- shapeType: '',
- /**
- * wether to generate key points for each shape
- * @protected
- * @type {Boolean}
- */
- generatePoints: false,
- attrOptions: {},
- sortable: false,
- startOnZero: true,
- visible: true,
- connectNulls: false,
- // 是否丢弃没有值的分组。
- ignoreEmptyGroup: false,
- // 是否已经初始化
- isInit: false
- };
- }
- init() {
- var self = this;
- var isInit = self.get('isInit');
- if (isInit) {
- return;
- }
- self._initAttrs();
- self._processData();
- self.set('isInit', true);
- }
- _getGroupScales() {
- var self = this;
- var scales = [];
- each(GROUP_ATTRS, function (attrName) {
- var attr = self.getAttr(attrName);
- if (attr) {
- var attrScales = attr.scales;
- each(attrScales, function (scale) {
- if (scale && scale.isCategory && scales.indexOf(scale) === -1) {
- scales.push(scale);
- }
- });
- }
- });
- return scales;
- }
- _groupData(data) {
- var self = this;
- var colDefs = self.get('colDefs');
- var groupScales = self._getGroupScales();
- if (groupScales.length) {
- var appendConditions = {};
- var names = [];
- each(groupScales, function (scale) {
- var field = scale.field;
- names.push(field);
- if (colDefs && colDefs[field] && colDefs[field].values) {
- // users have defined
- appendConditions[scale.field] = colDefs[field].values;
- }
- });
- return group$1(data, names, appendConditions);
- }
- return [data];
- }
- _setAttrOptions(attrName, attrCfg) {
- var options = this.get('attrOptions');
- options[attrName] = attrCfg;
- var attrs = this.get('attrs'); // 说明已经初始化过了
- if (Object.keys(attrs).length) {
- this._createAttr(attrName, attrCfg);
- }
- }
- _createAttrOption(attrName, field, cfg, defaultValues) {
- var attrCfg = {};
- attrCfg.field = field;
- if (cfg) {
- if (isFunction(cfg)) {
- attrCfg.callback = cfg;
- } else {
- attrCfg.values = cfg;
- }
- } else {
- attrCfg.values = defaultValues;
- }
- this._setAttrOptions(attrName, attrCfg);
- }
- _createAttr(type, option) {
- var self = this;
- var attrs = self.get('attrs');
- var coord = self.get('coord');
- var className = upperFirst(type);
- var fields = parseFields(option.field);
- if (type === 'position') {
- option.coord = coord;
- }
- var scales = [];
- for (var i = 0, len = fields.length; i < len; i++) {
- var field = fields[i];
- var scale = self._createScale(field);
- scales.push(scale);
- }
- if (type === 'position') {
- var yScale = scales[1]; // 饼图的处理,但是还不知道为啥
- if (coord.type === 'polar' && coord.transposed && self.hasAdjust('stack')) {
- if (yScale.values.length) {
- yScale.change({
- nice: false,
- min: 0,
- max: Math.max.apply(null, yScale.values)
- });
- }
- }
- }
- option.scales = scales;
- var attr = new Attr[className](option);
- attrs[type] = attr;
- return attr;
- }
- _initAttrs() {
- var self = this;
- var attrOptions = self.get('attrOptions');
- for (var type in attrOptions) {
- if (attrOptions.hasOwnProperty(type)) {
- this._createAttr(type, attrOptions[type]);
- }
- }
- }
- _createScale(field) {
- var scales = this.get('scales');
- var scale = scales[field];
- if (!scale) {
- scale = this.get('chart').createScale(field);
- scales[field] = scale;
- }
- return scale;
- }
- _processData() {
- var self = this;
- var data = this.get('data');
- var dataArray = [];
- var groupedArray = this._groupData(data);
- if (this.get('ignoreEmptyGroup')) {
- var yScale = this.getYScale();
- groupedArray = groupedArray.filter(function (group) {
- return group.some(function (item) {
- return typeof item[yScale.field] !== 'undefined';
- });
- });
- }
- for (var i = 0, len = groupedArray.length; i < len; i++) {
- var subData = groupedArray[i];
- var tempData = self._saveOrigin(subData);
- if (this.hasAdjust('dodge')) {
- self._numberic(tempData);
- }
- dataArray.push(tempData);
- }
- if (self.get('adjust')) {
- self._adjustData(dataArray);
- }
- if (self.get('sortable')) {
- self._sort(dataArray);
- }
- self.emit('afterprocessdata', {
- dataArray
- });
- self.set('mappingData', dataArray);
- self.set('dataArray', dataArray);
- return dataArray;
- }
- _saveOrigin(data) {
- var rst = [];
- for (var i = 0, len = data.length; i < len; i++) {
- var origin = data[i];
- var obj = {};
- for (var k in origin) {
- obj[k] = origin[k];
- }
- obj[FIELD_ORIGIN] = origin;
- rst.push(obj);
- }
- return rst;
- }
- _numberic(data) {
- var positionAttr = this.getAttr('position');
- var scales = positionAttr.scales;
- for (var j = 0, len = data.length; j < len; j++) {
- var obj = data[j];
- var count = Math.min(2, scales.length);
- for (var i = 0; i < count; i++) {
- var scale = scales[i];
- if (scale.isCategory) {
- var field = scale.field;
- obj[field] = scale.translate(obj[field]);
- }
- }
- }
- }
- _adjustData(dataArray) {
- var self = this;
- var adjust = self.get('adjust');
- if (adjust) {
- var adjustType = upperFirst(adjust.type);
- if (!base[adjustType]) {
- throw new Error('not support such adjust : ' + adjust);
- }
- var xScale = self.getXScale();
- var yScale = self.getYScale();
- var cfg = mix({
- xField: xScale.field,
- yField: yScale.field
- }, adjust);
- var adjustObject = new base[adjustType](cfg);
- adjustObject.processAdjust(dataArray);
- if (adjustType === 'Stack') {
- self._updateStackRange(yScale.field, yScale, dataArray);
- }
- }
- }
- _updateStackRange(field, scale, dataArray) {
- var mergeArray = merge(dataArray);
- var min = scale.min;
- var max = scale.max;
- for (var i = 0, len = mergeArray.length; i < len; i++) {
- var obj = mergeArray[i];
- var tmpMin = Math.min.apply(null, obj[field]);
- var tmpMax = Math.max.apply(null, obj[field]);
- if (tmpMin < min) {
- min = tmpMin;
- }
- if (tmpMax > max) {
- max = tmpMax;
- }
- }
- if (min < scale.min || max > scale.max) {
- scale.change({
- min,
- max
- });
- }
- }
- _sort(mappedArray) {
- var self = this;
- var xScale = self.getXScale();
- var {
- field,
- type
- } = xScale;
- if (type !== 'identity' && xScale.values.length > 1) {
- each(mappedArray, function (itemArr) {
- itemArr.sort(function (obj1, obj2) {
- if (type === 'timeCat') {
- return toTimeStamp(obj1[FIELD_ORIGIN][field]) - toTimeStamp(obj2[FIELD_ORIGIN][field]);
- }
- return xScale.translate(obj1[FIELD_ORIGIN][field]) - xScale.translate(obj2[FIELD_ORIGIN][field]);
- });
- });
- }
- self.set('hasSorted', true);
- self.set('dataArray', mappedArray);
- }
- paint() {
- var self = this;
- var dataArray = self.get('mappingData');
- var mappedArray = [];
- var shapeFactory = self.getShapeFactory();
- shapeFactory.setCoord(self.get('coord'));
- self._beforeMapping(dataArray);
- for (var i = 0, len = dataArray.length; i < len; i++) {
- var data = dataArray[i];
- if (data.length) {
- var mappedData = self._mapping(data);
- mappedArray.push(mappedData);
- self.draw(mappedData, shapeFactory);
- }
- }
- self.set('dataArray', mappedArray);
- }
- getShapeFactory() {
- var shapeFactory = this.get('shapeFactory');
- if (!shapeFactory) {
- var shapeType = this.get('shapeType');
- shapeFactory = Shape$1.getShapeFactory(shapeType);
- this.set('shapeFactory', shapeFactory);
- }
- return shapeFactory;
- }
- _mapping(data) {
- var self = this;
- var attrs = self.get('attrs');
- var yField = self.getYScale().field; // 用来缓存转换的值,减少mapping耗时
- var mappedCache = {};
- var mappedData = new Array(data.length);
- for (var k in attrs) {
- if (attrs.hasOwnProperty(k)) {
- var attr = attrs[k];
- var names = attr.names;
- var scales = attr.scales;
- for (var i = 0, len = data.length; i < len; i++) {
- var record = data[i];
- var mappedRecord = _objectSpread(_objectSpread({}, record), mappedData[i]);
- mappedRecord[FIELD_ORIGIN_Y] = record[yField]; // 获取视觉属性对应的value值
- // 位置的缓存命中率低,还是每次单独计算
- if (attr.type === 'position') {
- var values = self._getAttrValues(attr, record);
- for (var j = 0, _len = values.length; j < _len; j++) {
- var val = values[j];
- var name = names[j];
- mappedRecord[name] = isArray(val) && val.length === 1 ? val[0] : val;
- }
- } else {
- // 除了position其他都只有一项
- var _name = names[0];
- var field = scales[0].field;
- var value = record[field];
- var key = "".concat(_name).concat(value);
- var _values = mappedCache[key];
- if (!_values) {
- _values = self._getAttrValues(attr, record);
- mappedCache[key] = _values;
- }
- mappedRecord[_name] = _values[0];
- } // 设置新数组
- mappedData[i] = mappedRecord;
- }
- }
- }
- return mappedData;
- }
- _getAttrValues(attr, record) {
- var scales = attr.scales;
- var params = [];
- for (var i = 0, len = scales.length; i < len; i++) {
- var scale = scales[i];
- var field = scale.field;
- if (scale.type === 'identity') {
- params.push(scale.value);
- } else {
- params.push(record[field]);
- }
- }
- var values = attr.mapping(...params);
- return values;
- }
- getAttrValue(attrName, record) {
- var attr = this.getAttr(attrName);
- var rst = null;
- if (attr) {
- var values = this._getAttrValues(attr, record);
- rst = values[0];
- }
- return rst;
- }
- _beforeMapping(dataArray) {
- var self = this;
- if (self.get('generatePoints')) {
- self._generatePoints(dataArray);
- }
- }
- isInCircle() {
- var coord = this.get('coord');
- return coord && coord.isPolar;
- }
- getCallbackCfg(fields, cfg, origin) {
- if (!fields) {
- return cfg;
- }
- var tmpCfg = {};
- var params = fields.map(function (field) {
- return origin[field];
- });
- each(cfg, function (v, k) {
- if (isFunction(v)) {
- tmpCfg[k] = v.apply(null, params);
- } else {
- tmpCfg[k] = v;
- }
- });
- return tmpCfg;
- }
- getDrawCfg(obj) {
- var self = this;
- var isInCircle = self.isInCircle();
- var cfg = {
- origin: obj,
- x: obj.x,
- y: obj.y,
- color: obj.color,
- size: obj.size,
- shape: obj.shape,
- isInCircle,
- opacity: obj.opacity
- };
- var styleOptions = self.get('styleOptions');
- if (styleOptions && styleOptions.style) {
- cfg.style = self.getCallbackCfg(styleOptions.fields, styleOptions.style, obj[FIELD_ORIGIN]);
- }
- if (self.get('generatePoints')) {
- cfg.points = obj.points;
- cfg.nextPoints = obj.nextPoints;
- }
- if (isInCircle) {
- cfg.center = self.get('coord').center;
- }
- return cfg;
- }
- draw(data, shapeFactory) {
- var self = this;
- var container = self.get('container');
- var yScale = self.getYScale();
- each(data, function (obj, index) {
- if (yScale && isNil(obj._origin[yScale.field])) {
- return;
- }
- obj.index = index;
- var cfg = self.getDrawCfg(obj);
- var shape = obj.shape;
- self.drawShape(shape, obj, cfg, container, shapeFactory);
- });
- }
- drawShape(shape, shapeData, cfg, container, shapeFactory) {
- var gShape = shapeFactory.drawShape(shape, cfg, container);
- if (gShape) {
- each([].concat(gShape), function (s) {
- s.set('origin', shapeData);
- });
- }
- }
- _generatePoints(dataArray) {
- var self = this;
- var shapeFactory = self.getShapeFactory();
- var shapeAttr = self.getAttr('shape');
- each(dataArray, function (data) {
- for (var i = 0, len = data.length; i < len; i++) {
- var obj = data[i];
- var cfg = self.createShapePointsCfg(obj);
- var shape = shapeAttr ? self._getAttrValues(shapeAttr, obj) : null;
- var points = shapeFactory.getShapePoints(shape, cfg);
- obj.points = points;
- }
- }); // 添加nextPoints
- each(dataArray, function (data, index) {
- var nextData = dataArray[index + 1];
- if (nextData) {
- data[0].nextPoints = nextData[0].points;
- }
- });
- }
- /**
- * get the info of each shape
- * @protected
- * @param {Object} obj the data item
- * @return {Object} cfg return the result
- */
- createShapePointsCfg(obj) {
- var xScale = this.getXScale();
- var yScale = this.getYScale();
- var x = this._normalizeValues(obj[xScale.field], xScale);
- var y;
- if (yScale) {
- y = this._normalizeValues(obj[yScale.field], yScale);
- } else {
- y = obj.y ? obj.y : 0.1;
- }
- return {
- x,
- y,
- y0: yScale ? yScale.scale(this.getYMinValue()) : undefined
- };
- }
- getYMinValue() {
- var yScale = this.getYScale();
- var {
- min,
- max
- } = yScale;
- var value;
- if (this.get('startOnZero')) {
- if (max <= 0 && min <= 0) {
- value = max;
- } else {
- value = min >= 0 ? min : 0;
- }
- } else {
- value = min;
- }
- return value;
- }
- _normalizeValues(values, scale) {
- var rst = [];
- if (isArray(values)) {
- for (var i = 0, len = values.length; i < len; i++) {
- var v = values[i];
- rst.push(scale.scale(v));
- }
- } else {
- rst = scale.scale(values);
- }
- return rst;
- }
- getAttr(name) {
- return this.get('attrs')[name];
- }
- getXScale() {
- return this.getAttr('position').scales[0];
- }
- getYScale() {
- return this.getAttr('position').scales[1];
- }
- hasAdjust(adjust) {
- return this.get('adjust') && this.get('adjust').type === adjust;
- }
- _getSnap(scale, item, arr) {
- var i = 0;
- var values;
- var yField = this.getYScale().field; // 叠加的维度
- if (this.hasAdjust('stack') && scale.field === yField) {
- values = [];
- arr.forEach(function (obj) {
- values.push(obj[FIELD_ORIGIN_Y]);
- });
- for (var len = values.length; i < len; i++) {
- if (values[0][0] > item) {
- break;
- }
- if (values[values.length - 1][1] <= item) {
- i = values.length - 1;
- break;
- }
- if (values[i][0] <= item && values[i][1] > item) {
- break;
- }
- }
- } else {
- values = scale.values;
- values.sort(function (a, b) {
- return a - b;
- });
- for (var _len2 = values.length; i < _len2; i++) {
- // 如果只有1个点直接返回第1个点
- if (_len2 <= 1) {
- break;
- } // 第1个点和第2个点之间
- if ((values[0] + values[1]) / 2 > item) {
- break;
- } // 中间的点
- if ((values[i - 1] + values[i]) / 2 <= item && (values[i + 1] + values[i]) / 2 > item) {
- break;
- } // 最后2个点
- if ((values[values.length - 2] + values[values.length - 1]) / 2 <= item) {
- i = values.length - 1;
- break;
- }
- }
- }
- var result = values[i];
- return result;
- }
- getSnapRecords(point) {
- var self = this;
- var coord = self.get('coord');
- var xScale = self.getXScale();
- var yScale = self.getYScale();
- var xfield = xScale.field;
- var dataArray = self.get('dataArray');
- if (!this.get('hasSorted')) {
- this._sort(dataArray);
- }
- var rst = [];
- var invertPoint = coord.invertPoint(point);
- var invertPointX = invertPoint.x;
- if (self.isInCircle() && !coord.transposed && invertPointX > (1 + xScale.rangeMax()) / 2) {
- invertPointX = xScale.rangeMin();
- }
- var xValue = xScale.invert(invertPointX);
- if (!xScale.isCategory) {
- xValue = self._getSnap(xScale, xValue);
- }
- var tmp = [];
- dataArray.forEach(function (data) {
- data.forEach(function (obj) {
- var originValue = isNil(obj[FIELD_ORIGIN]) ? obj[xfield] : obj[FIELD_ORIGIN][xfield];
- if (self._isEqual(originValue, xValue, xScale)) {
- tmp.push(obj);
- }
- });
- }); // special for pie chart
- if (this.hasAdjust('stack') && coord.isPolar && coord.transposed) {
- if (invertPointX >= 0 && invertPointX <= 1) {
- var yValue = yScale.invert(invertPoint.y);
- yValue = self._getSnap(yScale, yValue, tmp);
- tmp.forEach(function (obj) {
- if (isArray(yValue) ? obj[FIELD_ORIGIN_Y].toString() === yValue.toString() : obj[FIELD_ORIGIN_Y] === yValue) {
- rst.push(obj);
- }
- });
- }
- } else {
- rst = tmp;
- }
- return rst;
- }
- getRecords(value) {
- var _this = this;
- var xScale = this.getXScale();
- var dataArray = this.get('dataArray');
- var xfield = xScale.field;
- return dataArray.map(function (data) {
- for (var len = data.length, i = len - 1; i >= 0; i--) {
- var obj = data[i];
- var originValue = isNil(obj[FIELD_ORIGIN]) ? obj[xfield] : obj[FIELD_ORIGIN][xfield];
- if (_this._isEqual(originValue, value, xScale)) {
- return obj;
- }
- }
- return null;
- });
- }
- _isEqual(originValue, value, scale) {
- if (scale.type === 'timeCat') {
- return toTimeStamp(originValue) === value;
- }
- return value === originValue;
- }
- position(field) {
- this._setAttrOptions('position', {
- field
- });
- return this;
- }
- color(field, values) {
- this._createAttrOption('color', field, values, Global.colors);
- return this;
- }
- size(field, values) {
- this._createAttrOption('size', field, values, Global.sizes);
- return this;
- }
- shape(field, values) {
- var type = this.get('type');
- var shapes = Global.shapes[type] || [];
- this._createAttrOption('shape', field, values, shapes);
- return this;
- }
- style(field, cfg) {
- var styleOptions = this.get('styleOptions');
- if (!styleOptions) {
- styleOptions = {};
- this.set('styleOptions', styleOptions);
- }
- if (isObject(field)) {
- cfg = field;
- field = null;
- }
- var fields;
- if (field) {
- fields = parseFields(field);
- }
- styleOptions.fields = fields;
- styleOptions.style = cfg;
- return this;
- }
- adjust(type) {
- if (isString(type)) {
- type = {
- type
- };
- }
- this.set('adjust', type);
- return this;
- }
- animate(cfg) {
- this.set('animateCfg', cfg);
- return this;
- }
- changeData(data) {
- this.set('data', data); // 改变数据后,情况度量,因为需要重新实例化
- this.set('scales', {});
- if (!this.get('isInit')) return;
- this.set('isInit', false);
- this.init();
- }
- clearInner() {
- var container = this.get('container');
- if (container) {
- container.clear(); // container.setMatrix([ 1, 0, 0, 1, 0, 0 ]);
- }
- }
- reset() {
- this.set('isInit', false);
- this.set('attrs', {});
- this.set('attrOptions', {});
- this.set('adjust', null);
- this.clearInner();
- }
- clear() {
- this.clearInner();
- }
- destroy() {
- this.set('isInit', false);
- this.clear();
- super.destroy();
- }
- _display(visible) {
- this.set('visible', visible);
- var container = this.get('container');
- var canvas = container.get('canvas');
- container.set('visible', visible);
- canvas.draw();
- }
- show() {
- this._display(true);
- }
- hide() {
- this._display(false);
- }
- }
- var methodCache = {};
- /**
- * 获取计算 ticks 的方法
- * @param key 键值
- * @returns 计算 ticks 的方法
- */
- function getTickMethod(key) {
- return methodCache[key];
- }
- /**
- * 注册计算 ticks 的方法
- * @param key 键值
- * @param method 方法
- */
- function registerTickMethod(key, method) {
- methodCache[key] = method;
- }
- var Scale = /** @class */ (function () {
- function Scale(cfg) {
- /**
- * 度量的类型
- */
- this.type = 'base';
- /**
- * 是否分类类型的度量
- */
- this.isCategory = false;
- /**
- * 是否线性度量,有linear, time 度量
- */
- this.isLinear = false;
- /**
- * 是否连续类型的度量,linear,time,log, pow, quantile, quantize 都支持
- */
- this.isContinuous = false;
- /**
- * 是否是常量的度量,传入和传出一致
- */
- this.isIdentity = false;
- this.values = [];
- this.range = [0, 1];
- this.ticks = [];
- this.__cfg__ = cfg;
- this.initCfg();
- this.init();
- }
- // 对于原始值的必要转换,如分类、时间字段需转换成数值,用transform/map命名可能更好
- Scale.prototype.translate = function (v) {
- return v;
- };
- /** 重新初始化 */
- Scale.prototype.change = function (cfg) {
- // 覆盖配置项,而不替代
- mix(this.__cfg__, cfg);
- this.init();
- };
- Scale.prototype.clone = function () {
- return this.constructor(this.__cfg__);
- };
- /** 获取坐标轴需要的ticks */
- Scale.prototype.getTicks = function () {
- var _this = this;
- return map(this.ticks, function (tick, idx) {
- if (isObject(tick)) {
- // 仅当符合Tick类型时才有意义
- return tick;
- }
- return {
- text: _this.getText(tick, idx),
- tickValue: tick,
- value: _this.scale(tick), // scaled
- };
- });
- };
- /** 获取Tick的格式化结果 */
- Scale.prototype.getText = function (value, key) {
- var formatter = this.formatter;
- var res = formatter ? formatter(value, key) : value;
- if (isNil(res) || !isFunction(res.toString)) {
- return '';
- }
- return res.toString();
- };
- // 获取配置项中的值,当前 scale 上的值可能会被修改
- Scale.prototype.getConfig = function (key) {
- return this.__cfg__[key];
- };
- // scale初始化
- Scale.prototype.init = function () {
- mix(this, this.__cfg__);
- this.setDomain();
- if (isEmpty(this.getConfig('ticks'))) {
- this.ticks = this.calculateTicks();
- }
- };
- // 子类上覆盖某些属性,不能直接在类上声明,否则会被覆盖
- Scale.prototype.initCfg = function () { };
- Scale.prototype.setDomain = function () { };
- Scale.prototype.calculateTicks = function () {
- var tickMethod = this.tickMethod;
- var ticks = [];
- if (isString(tickMethod)) {
- var method = getTickMethod(tickMethod);
- if (!method) {
- throw new Error('There is no method to to calculate ticks!');
- }
- ticks = method(this);
- }
- else if (isFunction(tickMethod)) {
- ticks = tickMethod(this);
- }
- return ticks;
- };
- // range 的最小值
- Scale.prototype.rangeMin = function () {
- return this.range[0];
- };
- // range 的最大值
- Scale.prototype.rangeMax = function () {
- return this.range[1];
- };
- /** 定义域转 0~1 */
- Scale.prototype.calcPercent = function (value, min, max) {
- if (isNumber(value)) {
- return (value - min) / (max - min);
- }
- return NaN;
- };
- /** 0~1转定义域 */
- Scale.prototype.calcValue = function (percent, min, max) {
- return min + percent * (max - min);
- };
- return Scale;
- }());
- /**
- * 分类度量
- * @class
- */
- var Category = /** @class */ (function (_super) {
- __extends(Category, _super);
- function Category() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'cat';
- _this.isCategory = true;
- return _this;
- }
- Category.prototype.buildIndexMap = function () {
- if (!this.translateIndexMap) {
- this.translateIndexMap = new Map();
- // 重新构建缓存
- for (var i = 0; i < this.values.length; i++) {
- this.translateIndexMap.set(this.values[i], i);
- }
- }
- };
- Category.prototype.translate = function (value) {
- // 按需构建 map
- this.buildIndexMap();
- // 找得到
- var idx = this.translateIndexMap.get(value);
- if (idx === undefined) {
- idx = isNumber(value) ? value : NaN;
- }
- return idx;
- };
- Category.prototype.scale = function (value) {
- var order = this.translate(value);
- // 分类数据允许 0.5 范围内调整
- // if (order < this.min - 0.5 || order > this.max + 0.5) {
- // return NaN;
- // }
- var percent = this.calcPercent(order, this.min, this.max);
- return this.calcValue(percent, this.rangeMin(), this.rangeMax());
- };
- Category.prototype.invert = function (scaledValue) {
- var domainRange = this.max - this.min;
- var percent = this.calcPercent(scaledValue, this.rangeMin(), this.rangeMax());
- var idx = Math.round(domainRange * percent) + this.min;
- if (idx < this.min || idx > this.max) {
- return NaN;
- }
- return this.values[idx];
- };
- Category.prototype.getText = function (value) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- var v = value;
- // value为index
- if (isNumber(value) && !this.values.includes(value)) {
- v = this.values[v];
- }
- return _super.prototype.getText.apply(this, __spreadArray([v], args, false));
- };
- // 复写属性
- Category.prototype.initCfg = function () {
- this.tickMethod = 'cat';
- };
- // 设置 min, max
- Category.prototype.setDomain = function () {
- // 用户有可能设置 min
- if (isNil(this.getConfig('min'))) {
- this.min = 0;
- }
- if (isNil(this.getConfig('max'))) {
- var size = this.values.length;
- this.max = size > 1 ? size - 1 : size;
- }
- // scale.init 的时候清除缓存
- if (this.translateIndexMap) {
- this.translateIndexMap = undefined;
- }
- };
- return Category;
- }(Scale));
- var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
- var twoDigitsOptional = "[1-9]\\d?";
- var twoDigits = "\\d\\d";
- var threeDigits = "\\d{3}";
- var fourDigits = "\\d{4}";
- var word = "[^\\s]+";
- var literal = /\[([^]*?)\]/gm;
- function shorten(arr, sLen) {
- var newArr = [];
- for (var i = 0, len = arr.length; i < len; i++) {
- newArr.push(arr[i].substr(0, sLen));
- }
- return newArr;
- }
- var monthUpdate = function (arrName) { return function (v, i18n) {
- var lowerCaseArr = i18n[arrName].map(function (v) { return v.toLowerCase(); });
- var index = lowerCaseArr.indexOf(v.toLowerCase());
- if (index > -1) {
- return index;
- }
- return null;
- }; };
- function assign(origObj) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- for (var _a = 0, args_1 = args; _a < args_1.length; _a++) {
- var obj = args_1[_a];
- for (var key in obj) {
- // @ts-ignore ex
- origObj[key] = obj[key];
- }
- }
- return origObj;
- }
- var dayNames = [
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday"
- ];
- var monthNames = [
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- ];
- var monthNamesShort = shorten(monthNames, 3);
- var dayNamesShort = shorten(dayNames, 3);
- var defaultI18n = {
- dayNamesShort: dayNamesShort,
- dayNames: dayNames,
- monthNamesShort: monthNamesShort,
- monthNames: monthNames,
- amPm: ["am", "pm"],
- DoFn: function (dayOfMonth) {
- return (dayOfMonth +
- ["th", "st", "nd", "rd"][dayOfMonth % 10 > 3
- ? 0
- : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]);
- }
- };
- var globalI18n = assign({}, defaultI18n);
- var setGlobalDateI18n = function (i18n) {
- return (globalI18n = assign(globalI18n, i18n));
- };
- var regexEscape = function (str) {
- return str.replace(/[|\\{()[^$+*?.-]/g, "\\$&");
- };
- var pad = function (val, len) {
- if (len === void 0) { len = 2; }
- val = String(val);
- while (val.length < len) {
- val = "0" + val;
- }
- return val;
- };
- var formatFlags = {
- D: function (dateObj) { return String(dateObj.getDate()); },
- DD: function (dateObj) { return pad(dateObj.getDate()); },
- Do: function (dateObj, i18n) {
- return i18n.DoFn(dateObj.getDate());
- },
- d: function (dateObj) { return String(dateObj.getDay()); },
- dd: function (dateObj) { return pad(dateObj.getDay()); },
- ddd: function (dateObj, i18n) {
- return i18n.dayNamesShort[dateObj.getDay()];
- },
- dddd: function (dateObj, i18n) {
- return i18n.dayNames[dateObj.getDay()];
- },
- M: function (dateObj) { return String(dateObj.getMonth() + 1); },
- MM: function (dateObj) { return pad(dateObj.getMonth() + 1); },
- MMM: function (dateObj, i18n) {
- return i18n.monthNamesShort[dateObj.getMonth()];
- },
- MMMM: function (dateObj, i18n) {
- return i18n.monthNames[dateObj.getMonth()];
- },
- YY: function (dateObj) {
- return pad(String(dateObj.getFullYear()), 4).substr(2);
- },
- YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); },
- h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); },
- hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); },
- H: function (dateObj) { return String(dateObj.getHours()); },
- HH: function (dateObj) { return pad(dateObj.getHours()); },
- m: function (dateObj) { return String(dateObj.getMinutes()); },
- mm: function (dateObj) { return pad(dateObj.getMinutes()); },
- s: function (dateObj) { return String(dateObj.getSeconds()); },
- ss: function (dateObj) { return pad(dateObj.getSeconds()); },
- S: function (dateObj) {
- return String(Math.round(dateObj.getMilliseconds() / 100));
- },
- SS: function (dateObj) {
- return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
- },
- SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); },
- a: function (dateObj, i18n) {
- return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
- },
- A: function (dateObj, i18n) {
- return dateObj.getHours() < 12
- ? i18n.amPm[0].toUpperCase()
- : i18n.amPm[1].toUpperCase();
- },
- ZZ: function (dateObj) {
- var offset = dateObj.getTimezoneOffset();
- return ((offset > 0 ? "-" : "+") +
- pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4));
- },
- Z: function (dateObj) {
- var offset = dateObj.getTimezoneOffset();
- return ((offset > 0 ? "-" : "+") +
- pad(Math.floor(Math.abs(offset) / 60), 2) +
- ":" +
- pad(Math.abs(offset) % 60, 2));
- }
- };
- var monthParse = function (v) { return +v - 1; };
- var emptyDigits = [null, twoDigitsOptional];
- var emptyWord = [null, word];
- var amPm = [
- "isPm",
- word,
- function (v, i18n) {
- var val = v.toLowerCase();
- if (val === i18n.amPm[0]) {
- return 0;
- }
- else if (val === i18n.amPm[1]) {
- return 1;
- }
- return null;
- }
- ];
- var timezoneOffset = [
- "timezoneOffset",
- "[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",
- function (v) {
- var parts = (v + "").match(/([+-]|\d\d)/gi);
- if (parts) {
- var minutes = +parts[1] * 60 + parseInt(parts[2], 10);
- return parts[0] === "+" ? minutes : -minutes;
- }
- return 0;
- }
- ];
- var parseFlags = {
- D: ["day", twoDigitsOptional],
- DD: ["day", twoDigits],
- Do: ["day", twoDigitsOptional + word, function (v) { return parseInt(v, 10); }],
- M: ["month", twoDigitsOptional, monthParse],
- MM: ["month", twoDigits, monthParse],
- YY: [
- "year",
- twoDigits,
- function (v) {
- var now = new Date();
- var cent = +("" + now.getFullYear()).substr(0, 2);
- return +("" + (+v > 68 ? cent - 1 : cent) + v);
- }
- ],
- h: ["hour", twoDigitsOptional, undefined, "isPm"],
- hh: ["hour", twoDigits, undefined, "isPm"],
- H: ["hour", twoDigitsOptional],
- HH: ["hour", twoDigits],
- m: ["minute", twoDigitsOptional],
- mm: ["minute", twoDigits],
- s: ["second", twoDigitsOptional],
- ss: ["second", twoDigits],
- YYYY: ["year", fourDigits],
- S: ["millisecond", "\\d", function (v) { return +v * 100; }],
- SS: ["millisecond", twoDigits, function (v) { return +v * 10; }],
- SSS: ["millisecond", threeDigits],
- d: emptyDigits,
- dd: emptyDigits,
- ddd: emptyWord,
- dddd: emptyWord,
- MMM: ["month", word, monthUpdate("monthNamesShort")],
- MMMM: ["month", word, monthUpdate("monthNames")],
- a: amPm,
- A: amPm,
- ZZ: timezoneOffset,
- Z: timezoneOffset
- };
- // Some common format strings
- var globalMasks = {
- default: "ddd MMM DD YYYY HH:mm:ss",
- shortDate: "M/D/YY",
- mediumDate: "MMM D, YYYY",
- longDate: "MMMM D, YYYY",
- fullDate: "dddd, MMMM D, YYYY",
- isoDate: "YYYY-MM-DD",
- isoDateTime: "YYYY-MM-DDTHH:mm:ssZ",
- shortTime: "HH:mm",
- mediumTime: "HH:mm:ss",
- longTime: "HH:mm:ss.SSS"
- };
- var setGlobalDateMasks = function (masks) { return assign(globalMasks, masks); };
- /***
- * Format a date
- * @method format
- * @param {Date|number} dateObj
- * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
- * @returns {string} Formatted date string
- */
- var format = function (dateObj, mask, i18n) {
- if (mask === void 0) { mask = globalMasks["default"]; }
- if (i18n === void 0) { i18n = {}; }
- if (typeof dateObj === "number") {
- dateObj = new Date(dateObj);
- }
- if (Object.prototype.toString.call(dateObj) !== "[object Date]" ||
- isNaN(dateObj.getTime())) {
- throw new Error("Invalid Date pass to format");
- }
- mask = globalMasks[mask] || mask;
- var literals = [];
- // Make literals inactive by replacing them with @@@
- mask = mask.replace(literal, function ($0, $1) {
- literals.push($1);
- return "@@@";
- });
- var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
- // Apply formatting rules
- mask = mask.replace(token, function ($0) {
- return formatFlags[$0](dateObj, combinedI18nSettings);
- });
- // Inline literal values back into the formatted value
- return mask.replace(/@@@/g, function () { return literals.shift(); });
- };
- /**
- * Parse a date string into a Javascript Date object /
- * @method parse
- * @param {string} dateStr Date string
- * @param {string} format Date parse format
- * @param {i18n} I18nSettingsOptional Full or subset of I18N settings
- * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format
- */
- function parse(dateStr, format, i18n) {
- if (i18n === void 0) { i18n = {}; }
- if (typeof format !== "string") {
- throw new Error("Invalid format in fecha parse");
- }
- // Check to see if the format is actually a mask
- format = globalMasks[format] || format;
- // Avoid regular expression denial of service, fail early for really long strings
- // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
- if (dateStr.length > 1000) {
- return null;
- }
- // Default to the beginning of the year.
- var today = new Date();
- var dateInfo = {
- year: today.getFullYear(),
- month: 0,
- day: 1,
- hour: 0,
- minute: 0,
- second: 0,
- millisecond: 0,
- isPm: null,
- timezoneOffset: null
- };
- var parseInfo = [];
- var literals = [];
- // Replace all the literals with @@@. Hopefully a string that won't exist in the format
- var newFormat = format.replace(literal, function ($0, $1) {
- literals.push(regexEscape($1));
- return "@@@";
- });
- var specifiedFields = {};
- var requiredFields = {};
- // Change every token that we find into the correct regex
- newFormat = regexEscape(newFormat).replace(token, function ($0) {
- var info = parseFlags[$0];
- var field = info[0], regex = info[1], requiredField = info[3];
- // Check if the person has specified the same field twice. This will lead to confusing results.
- if (specifiedFields[field]) {
- throw new Error("Invalid format. " + field + " specified twice in format");
- }
- specifiedFields[field] = true;
- // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified
- if (requiredField) {
- requiredFields[requiredField] = true;
- }
- parseInfo.push(info);
- return "(" + regex + ")";
- });
- // Check all the required fields are present
- Object.keys(requiredFields).forEach(function (field) {
- if (!specifiedFields[field]) {
- throw new Error("Invalid format. " + field + " is required in specified format");
- }
- });
- // Add back all the literals after
- newFormat = newFormat.replace(/@@@/g, function () { return literals.shift(); });
- // Check if the date string matches the format. If it doesn't return null
- var matches = dateStr.match(new RegExp(newFormat, "i"));
- if (!matches) {
- return null;
- }
- var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
- // For each match, call the parser function for that date part
- for (var i = 1; i < matches.length; i++) {
- var _a = parseInfo[i - 1], field = _a[0], parser = _a[2];
- var value = parser
- ? parser(matches[i], combinedI18nSettings)
- : +matches[i];
- // If the parser can't make sense of the value, return null
- if (value == null) {
- return null;
- }
- dateInfo[field] = value;
- }
- if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {
- dateInfo.hour = +dateInfo.hour + 12;
- }
- else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {
- dateInfo.hour = 0;
- }
- var dateWithoutTZ = new Date(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute, dateInfo.second, dateInfo.millisecond);
- var validateFields = [
- ["month", "getMonth"],
- ["day", "getDate"],
- ["hour", "getHours"],
- ["minute", "getMinutes"],
- ["second", "getSeconds"]
- ];
- for (var i = 0, len = validateFields.length; i < len; i++) {
- // Check to make sure the date field is within the allowed range. Javascript dates allows values
- // outside the allowed range. If the values don't match the value was invalid
- if (specifiedFields[validateFields[i][0]] &&
- dateInfo[validateFields[i][0]] !== dateWithoutTZ[validateFields[i][1]]()) {
- return null;
- }
- }
- if (dateInfo.timezoneOffset == null) {
- return dateWithoutTZ;
- }
- return new Date(Date.UTC(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute - dateInfo.timezoneOffset, dateInfo.second, dateInfo.millisecond));
- }
- var fecha = {
- format: format,
- parse: parse,
- defaultI18n: defaultI18n,
- setGlobalDateI18n: setGlobalDateI18n,
- setGlobalDateMasks: setGlobalDateMasks
- };
- var fecha1 = /*#__PURE__*/Object.freeze({
- __proto__: null,
- 'default': fecha,
- assign: assign,
- format: format,
- parse: parse,
- defaultI18n: defaultI18n,
- setGlobalDateI18n: setGlobalDateI18n,
- setGlobalDateMasks: setGlobalDateMasks
- });
- /**
- * 二分右侧查找
- * https://github.com/d3/d3-array/blob/master/src/bisector.js
- */
- function bisector (getter) {
- /**
- * x: 目标值
- * lo: 起始位置
- * hi: 结束位置
- */
- return function (a, x, _lo, _hi) {
- var lo = isNil(_lo) ? 0 : _lo;
- var hi = isNil(_hi) ? a.length : _hi;
- while (lo < hi) {
- var mid = (lo + hi) >>> 1;
- if (getter(a[mid]) > x) {
- hi = mid;
- }
- else {
- lo = mid + 1;
- }
- }
- return lo;
- };
- }
- var FORMAT_METHOD = 'format';
- function timeFormat(time, mask) {
- var method = fecha1[FORMAT_METHOD] || fecha[FORMAT_METHOD];
- return method(time, mask);
- }
- /**
- * 转换成时间戳
- * @param value 时间值
- */
- function toTimeStamp$1(value) {
- if (isString(value)) {
- if (value.indexOf('T') > 0) {
- value = new Date(value).getTime();
- }
- else {
- // new Date('2010/01/10') 和 new Date('2010-01-10') 的差别在于:
- // 如果仅有年月日时,前者是带有时区的: Fri Jan 10 2020 02:40:13 GMT+0800 (中国标准时间)
- // 后者会格式化成 Sun Jan 10 2010 08:00:00 GMT+0800 (中国标准时间)
- value = new Date(value.replace(/-/gi, '/')).getTime();
- }
- }
- if (isDate(value)) {
- value = value.getTime();
- }
- return value;
- }
- var SECOND = 1000;
- var MINUTE = 60 * SECOND;
- var HOUR = 60 * MINUTE;
- var DAY = 24 * HOUR;
- var MONTH = DAY * 31;
- var YEAR = DAY * 365;
- var intervals = [
- ['HH:mm:ss', SECOND],
- ['HH:mm:ss', SECOND * 10],
- ['HH:mm:ss', SECOND * 30],
- ['HH:mm', MINUTE],
- ['HH:mm', MINUTE * 10],
- ['HH:mm', MINUTE * 30],
- ['HH', HOUR],
- ['HH', HOUR * 6],
- ['HH', HOUR * 12],
- ['YYYY-MM-DD', DAY],
- ['YYYY-MM-DD', DAY * 4],
- ['YYYY-WW', DAY * 7],
- ['YYYY-MM', MONTH],
- ['YYYY-MM', MONTH * 4],
- ['YYYY-MM', MONTH * 6],
- ['YYYY', DAY * 380], // 借鉴echarts,保证每个周期累加时不会碰到恰巧不够的问题
- ];
- function getTickInterval(min, max, tickCount) {
- var target = (max - min) / tickCount;
- var idx = bisector(function (o) { return o[1]; })(intervals, target) - 1;
- var interval = intervals[idx];
- if (idx < 0) {
- interval = intervals[0];
- }
- else if (idx >= intervals.length) {
- interval = last(intervals);
- }
- return interval;
- }
- /**
- * 时间分类度量
- * @class
- */
- var TimeCat = /** @class */ (function (_super) {
- __extends(TimeCat, _super);
- function TimeCat() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'timeCat';
- return _this;
- }
- /**
- * @override
- */
- TimeCat.prototype.translate = function (value) {
- value = toTimeStamp$1(value);
- var index = this.values.indexOf(value);
- if (index === -1) {
- if (isNumber(value) && value < this.values.length) {
- index = value;
- }
- else {
- index = NaN;
- }
- }
- return index;
- };
- /**
- * 由于时间类型数据需要转换一下,所以复写 getText
- * @override
- */
- TimeCat.prototype.getText = function (value, tickIndex) {
- var index = this.translate(value);
- if (index > -1) {
- var result = this.values[index];
- var formatter = this.formatter;
- result = formatter ? formatter(result, tickIndex) : timeFormat(result, this.mask);
- return result;
- }
- return value;
- };
- TimeCat.prototype.initCfg = function () {
- this.tickMethod = 'time-cat';
- this.mask = 'YYYY-MM-DD';
- this.tickCount = 7; // 一般时间数据会显示 7, 14, 30 天的数字
- };
- TimeCat.prototype.setDomain = function () {
- var values = this.values;
- // 针对时间分类类型,会将时间统一转换为时间戳
- each(values, function (v, i) {
- values[i] = toTimeStamp$1(v);
- });
- values.sort(function (v1, v2) {
- return v1 - v2;
- });
- _super.prototype.setDomain.call(this);
- };
- return TimeCat;
- }(Category));
- /**
- * 连续度量的基类
- * @class
- */
- var Continuous = /** @class */ (function (_super) {
- __extends(Continuous, _super);
- function Continuous() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.isContinuous = true;
- return _this;
- }
- Continuous.prototype.scale = function (value) {
- if (isNil(value)) {
- return NaN;
- }
- var rangeMin = this.rangeMin();
- var rangeMax = this.rangeMax();
- var max = this.max;
- var min = this.min;
- if (max === min) {
- return rangeMin;
- }
- var percent = this.getScalePercent(value);
- return rangeMin + percent * (rangeMax - rangeMin);
- };
- Continuous.prototype.init = function () {
- _super.prototype.init.call(this);
- // init 完成后保证 min, max 包含 ticks 的范围
- var ticks = this.ticks;
- var firstTick = head(ticks);
- var lastTick = last(ticks);
- if (firstTick < this.min) {
- this.min = firstTick;
- }
- if (lastTick > this.max) {
- this.max = lastTick;
- }
- // strict-limit 方式
- if (!isNil(this.minLimit)) {
- this.min = firstTick;
- }
- if (!isNil(this.maxLimit)) {
- this.max = lastTick;
- }
- };
- Continuous.prototype.setDomain = function () {
- var _a = getRange(this.values), min = _a.min, max = _a.max;
- if (isNil(this.min)) {
- this.min = min;
- }
- if (isNil(this.max)) {
- this.max = max;
- }
- if (this.min > this.max) {
- this.min = min;
- this.max = max;
- }
- };
- Continuous.prototype.calculateTicks = function () {
- var _this = this;
- var ticks = _super.prototype.calculateTicks.call(this);
- if (!this.nice) {
- ticks = filter(ticks, function (tick) {
- return tick >= _this.min && tick <= _this.max;
- });
- }
- return ticks;
- };
- // 计算原始值值占的百分比
- Continuous.prototype.getScalePercent = function (value) {
- var max = this.max;
- var min = this.min;
- return (value - min) / (max - min);
- };
- Continuous.prototype.getInvertPercent = function (value) {
- return (value - this.rangeMin()) / (this.rangeMax() - this.rangeMin());
- };
- return Continuous;
- }(Scale));
- /**
- * 线性度量
- * @class
- */
- var Linear = /** @class */ (function (_super) {
- __extends(Linear, _super);
- function Linear() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'linear';
- _this.isLinear = true;
- return _this;
- }
- Linear.prototype.invert = function (value) {
- var percent = this.getInvertPercent(value);
- return this.min + percent * (this.max - this.min);
- };
- Linear.prototype.initCfg = function () {
- this.tickMethod = 'wilkinson-extended';
- this.nice = false;
- };
- return Linear;
- }(Continuous));
- // 求以a为次幂,结果为b的基数,如 x^^a = b;求x
- // 虽然数学上 b 不支持负数,但是这里需要支持 负数
- function calBase(a, b) {
- var e = Math.E;
- var value;
- if (b >= 0) {
- value = Math.pow(e, Math.log(b) / a); // 使用换底公式求底
- }
- else {
- value = Math.pow(e, Math.log(-b) / a) * -1; // 使用换底公式求底
- }
- return value;
- }
- function log(a, b) {
- if (a === 1) {
- return 1;
- }
- return Math.log(b) / Math.log(a);
- }
- function getLogPositiveMin(values, base, max) {
- if (isNil(max)) {
- max = Math.max.apply(null, values);
- }
- var positiveMin = max;
- each(values, function (value) {
- if (value > 0 && value < positiveMin) {
- positiveMin = value;
- }
- });
- if (positiveMin === max) {
- positiveMin = max / base;
- }
- if (positiveMin > 1) {
- positiveMin = 1;
- }
- return positiveMin;
- }
- /**
- * Log 度量,处理非均匀分布
- */
- var Log = /** @class */ (function (_super) {
- __extends(Log, _super);
- function Log() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'log';
- return _this;
- }
- /**
- * @override
- */
- Log.prototype.invert = function (value) {
- var base = this.base;
- var max = log(base, this.max);
- var rangeMin = this.rangeMin();
- var range = this.rangeMax() - rangeMin;
- var min;
- var positiveMin = this.positiveMin;
- if (positiveMin) {
- if (value === 0) {
- return 0;
- }
- min = log(base, positiveMin / base);
- var appendPercent = (1 / (max - min)) * range; // 0 到 positiveMin的占比
- if (value < appendPercent) {
- // 落到 0 - positiveMin 之间
- return (value / appendPercent) * positiveMin;
- }
- }
- else {
- min = log(base, this.min);
- }
- var percent = (value - rangeMin) / range;
- var tmp = percent * (max - min) + min;
- return Math.pow(base, tmp);
- };
- Log.prototype.initCfg = function () {
- this.tickMethod = 'log';
- this.base = 10;
- this.tickCount = 6;
- this.nice = true;
- };
- // 设置
- Log.prototype.setDomain = function () {
- _super.prototype.setDomain.call(this);
- var min = this.min;
- if (min < 0) {
- throw new Error('When you use log scale, the minimum value must be greater than zero!');
- }
- if (min === 0) {
- this.positiveMin = getLogPositiveMin(this.values, this.base, this.max);
- }
- };
- // 根据当前值获取占比
- Log.prototype.getScalePercent = function (value) {
- var max = this.max;
- var min = this.min;
- if (max === min) {
- return 0;
- }
- // 如果值小于等于0,则按照0处理
- if (value <= 0) {
- return 0;
- }
- var base = this.base;
- var positiveMin = this.positiveMin;
- // 如果min == 0, 则根据比0大的最小值,计算比例关系。这个最小值作为坐标轴上的第二个tick,第一个是0但是不显示
- if (positiveMin) {
- min = (positiveMin * 1) / base;
- }
- var percent;
- // 如果数值小于次小值,那么就计算 value / 次小值 占整体的比例
- if (value < positiveMin) {
- percent = value / positiveMin / (log(base, max) - log(base, min));
- }
- else {
- percent = (log(base, value) - log(base, min)) / (log(base, max) - log(base, min));
- }
- return percent;
- };
- return Log;
- }(Continuous));
- /**
- * Pow 度量,处理非均匀分布
- */
- var Pow = /** @class */ (function (_super) {
- __extends(Pow, _super);
- function Pow() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'pow';
- return _this;
- }
- /**
- * @override
- */
- Pow.prototype.invert = function (value) {
- var percent = this.getInvertPercent(value);
- var exponent = this.exponent;
- var max = calBase(exponent, this.max);
- var min = calBase(exponent, this.min);
- var tmp = percent * (max - min) + min;
- var factor = tmp >= 0 ? 1 : -1;
- return Math.pow(tmp, exponent) * factor;
- };
- Pow.prototype.initCfg = function () {
- this.tickMethod = 'pow';
- this.exponent = 2;
- this.tickCount = 5;
- this.nice = true;
- };
- // 获取度量计算时,value占的定义域百分比
- Pow.prototype.getScalePercent = function (value) {
- var max = this.max;
- var min = this.min;
- if (max === min) {
- return 0;
- }
- var exponent = this.exponent;
- var percent = (calBase(exponent, value) - calBase(exponent, min)) / (calBase(exponent, max) - calBase(exponent, min));
- return percent;
- };
- return Pow;
- }(Continuous));
- /**
- * 时间度量
- * @class
- */
- var Time = /** @class */ (function (_super) {
- __extends(Time, _super);
- function Time() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'time';
- return _this;
- }
- /**
- * @override
- */
- Time.prototype.getText = function (value, index) {
- var numberValue = this.translate(value);
- var formatter = this.formatter;
- return formatter ? formatter(numberValue, index) : timeFormat(numberValue, this.mask);
- };
- /**
- * @override
- */
- Time.prototype.scale = function (value) {
- var v = value;
- if (isString(v) || isDate(v)) {
- v = this.translate(v);
- }
- return _super.prototype.scale.call(this, v);
- };
- /**
- * 将时间转换成数字
- * @override
- */
- Time.prototype.translate = function (v) {
- return toTimeStamp$1(v);
- };
- Time.prototype.initCfg = function () {
- this.tickMethod = 'time-pretty';
- this.mask = 'YYYY-MM-DD';
- this.tickCount = 7;
- this.nice = false;
- };
- Time.prototype.setDomain = function () {
- var values = this.values;
- // 是否设置了 min, max,而不是直接取 this.min, this.max
- var minConfig = this.getConfig('min');
- var maxConfig = this.getConfig('max');
- // 如果设置了 min,max 则转换成时间戳
- if (!isNil(minConfig) || !isNumber(minConfig)) {
- this.min = this.translate(this.min);
- }
- if (!isNil(maxConfig) || !isNumber(maxConfig)) {
- this.max = this.translate(this.max);
- }
- // 没有设置 min, max 时
- if (values && values.length) {
- // 重新计算最大最小值
- var timeStamps_1 = [];
- var min_1 = Infinity; // 最小值
- var secondMin_1 = min_1; // 次小值
- var max_1 = 0;
- // 使用一个循环,计算min,max,secondMin
- each(values, function (v) {
- var timeStamp = toTimeStamp$1(v);
- if (isNaN(timeStamp)) {
- throw new TypeError("Invalid Time: " + v + " in time scale!");
- }
- if (min_1 > timeStamp) {
- secondMin_1 = min_1;
- min_1 = timeStamp;
- }
- else if (secondMin_1 > timeStamp) {
- secondMin_1 = timeStamp;
- }
- if (max_1 < timeStamp) {
- max_1 = timeStamp;
- }
- timeStamps_1.push(timeStamp);
- });
- // 存在多个值时,设置最小间距
- if (values.length > 1) {
- this.minTickInterval = secondMin_1 - min_1;
- }
- if (isNil(minConfig)) {
- this.min = min_1;
- }
- if (isNil(maxConfig)) {
- this.max = max_1;
- }
- }
- };
- return Time;
- }(Linear));
- /**
- * 分段度量
- */
- var Quantize = /** @class */ (function (_super) {
- __extends(Quantize, _super);
- function Quantize() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'quantize';
- return _this;
- }
- Quantize.prototype.invert = function (value) {
- var ticks = this.ticks;
- var length = ticks.length;
- var percent = this.getInvertPercent(value);
- var minIndex = Math.floor(percent * (length - 1));
- // 最后一个
- if (minIndex >= length - 1) {
- return last(ticks);
- }
- // 超出左边界, 则取第一个
- if (minIndex < 0) {
- return head(ticks);
- }
- var minTick = ticks[minIndex];
- var nextTick = ticks[minIndex + 1];
- // 比当前值小的 tick 在度量上的占比
- var minIndexPercent = minIndex / (length - 1);
- var maxIndexPercent = (minIndex + 1) / (length - 1);
- return minTick + (percent - minIndexPercent) / (maxIndexPercent - minIndexPercent) * (nextTick - minTick);
- };
- Quantize.prototype.initCfg = function () {
- this.tickMethod = 'r-pretty';
- this.tickCount = 5;
- this.nice = true;
- };
- Quantize.prototype.calculateTicks = function () {
- var ticks = _super.prototype.calculateTicks.call(this);
- if (!this.nice) { // 如果 nice = false ,补充 min, max
- if (last(ticks) !== this.max) {
- ticks.push(this.max);
- }
- if (head(ticks) !== this.min) {
- ticks.unshift(this.min);
- }
- }
- return ticks;
- };
- // 计算当前值在刻度中的占比
- Quantize.prototype.getScalePercent = function (value) {
- var ticks = this.ticks;
- // 超出左边界
- if (value < head(ticks)) {
- return 0;
- }
- // 超出右边界
- if (value > last(ticks)) {
- return 1;
- }
- var minIndex = 0;
- each(ticks, function (tick, index) {
- if (value >= tick) {
- minIndex = index;
- }
- else {
- return false;
- }
- });
- return minIndex / (ticks.length - 1);
- };
- return Quantize;
- }(Continuous));
- var Quantile = /** @class */ (function (_super) {
- __extends(Quantile, _super);
- function Quantile() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'quantile';
- return _this;
- }
- Quantile.prototype.initCfg = function () {
- this.tickMethod = 'quantile';
- this.tickCount = 5;
- this.nice = true;
- };
- return Quantile;
- }(Quantize));
- var map$2 = {};
- function getClass(key) {
- return map$2[key];
- }
- function registerClass(key, cls) {
- if (getClass(key)) {
- throw new Error("type '" + key + "' existed.");
- }
- map$2[key] = cls;
- }
- /**
- * identity scale原则上是定义域和值域一致,scale/invert方法也是一致的
- * 参考R的实现:https://github.com/r-lib/scales/blob/master/R/pal-identity.r
- * 参考d3的实现(做了下转型):https://github.com/d3/d3-scale/blob/master/src/identity.js
- */
- var Identity = /** @class */ (function (_super) {
- __extends(Identity, _super);
- function Identity() {
- var _this = _super !== null && _super.apply(this, arguments) || this;
- _this.type = 'identity';
- _this.isIdentity = true;
- return _this;
- }
- Identity.prototype.calculateTicks = function () {
- return this.values;
- };
- Identity.prototype.scale = function (value) {
- // 如果传入的值不等于 identity 的值,则直接返回,用于一维图时的 dodge
- if (this.values[0] !== value && isNumber(value)) {
- return value;
- }
- return this.range[0];
- };
- Identity.prototype.invert = function (value) {
- var range = this.range;
- if (value < range[0] || value > range[1]) {
- return NaN;
- }
- return this.values[0];
- };
- return Identity;
- }(Scale));
- // 为了解决 js 运算的精度问题
- function prettyNumber(n) {
- return Math.abs(n) < 1e-15 ? n : parseFloat(n.toFixed(15));
- }
- var DEFAULT_Q = [1, 5, 2, 2.5, 4, 3];
- var eps = Number.EPSILON * 100;
- function mod$1(n, m) {
- return ((n % m) + m) % m;
- }
- function round(n) {
- return Math.round(n * 1e12) / 1e12;
- }
- function simplicity(q, Q, j, lmin, lmax, lstep) {
- var n = size(Q);
- var i = indexOf$1(Q, q);
- var v = 0;
- var m = mod$1(lmin, lstep);
- if ((m < eps || lstep - m < eps) && lmin <= 0 && lmax >= 0) {
- v = 1;
- }
- return 1 - i / (n - 1) - j + v;
- }
- function simplicityMax(q, Q, j) {
- var n = size(Q);
- var i = indexOf$1(Q, q);
- var v = 1;
- return 1 - i / (n - 1) - j + v;
- }
- function density(k, m, dMin, dMax, lMin, lMax) {
- var r = (k - 1) / (lMax - lMin);
- var rt = (m - 1) / (Math.max(lMax, dMax) - Math.min(dMin, lMin));
- return 2 - Math.max(r / rt, rt / r);
- }
- function densityMax(k, m) {
- if (k >= m) {
- return 2 - (k - 1) / (m - 1);
- }
- return 1;
- }
- function coverage(dMin, dMax, lMin, lMax) {
- var range = dMax - dMin;
- return 1 - (0.5 * (Math.pow((dMax - lMax), 2) + Math.pow((dMin - lMin), 2))) / Math.pow((0.1 * range), 2);
- }
- function coverageMax(dMin, dMax, span) {
- var range = dMax - dMin;
- if (span > range) {
- var half = (span - range) / 2;
- return 1 - Math.pow(half, 2) / Math.pow((0.1 * range), 2);
- }
- return 1;
- }
- function legibility() {
- return 1;
- }
- /**
- * An Extension of Wilkinson's Algorithm for Position Tick Labels on Axes
- * https://www.yuque.com/preview/yuque/0/2019/pdf/185317/1546999150858-45c3b9c2-4e86-4223-bf1a-8a732e8195ed.pdf
- * @param dMin 最小值
- * @param dMax 最大值
- * @param m tick个数
- * @param onlyLoose 是否允许扩展min、max,不绝对强制,例如[3, 97]
- * @param Q nice numbers集合
- * @param w 四个优化组件的权重
- */
- function extended(dMin, dMax, n, onlyLoose, Q, w) {
- if (n === void 0) { n = 5; }
- if (onlyLoose === void 0) { onlyLoose = true; }
- if (Q === void 0) { Q = DEFAULT_Q; }
- if (w === void 0) { w = [0.25, 0.2, 0.5, 0.05]; }
- // 处理小于 0 和小数的 tickCount
- var m = n < 0 ? 0 : Math.round(n);
- // nan 也会导致异常
- if (Number.isNaN(dMin) || Number.isNaN(dMax) || typeof dMin !== 'number' || typeof dMax !== 'number' || !m) {
- return {
- min: 0,
- max: 0,
- ticks: [],
- };
- }
- // js 极大值极小值问题,差值小于 1e-15 会导致计算出错
- if (dMax - dMin < 1e-15 || m === 1) {
- return {
- min: dMin,
- max: dMax,
- ticks: [dMin],
- };
- }
- var best = {
- score: -2,
- lmin: 0,
- lmax: 0,
- lstep: 0,
- };
- var j = 1;
- while (j < Infinity) {
- for (var i = 0; i < Q.length; i += 1) {
- var q = Q[i];
- var sm = simplicityMax(q, Q, j);
- if (w[0] * sm + w[1] + w[2] + w[3] < best.score) {
- j = Infinity;
- break;
- }
- var k = 2;
- while (k < Infinity) {
- var dm = densityMax(k, m);
- if (w[0] * sm + w[1] + w[2] * dm + w[3] < best.score) {
- break;
- }
- var delta = (dMax - dMin) / (k + 1) / j / q;
- var z = Math.ceil(Math.log10(delta));
- while (z < Infinity) {
- var step = j * q * Math.pow(10, z);
- var cm = coverageMax(dMin, dMax, step * (k - 1));
- if (w[0] * sm + w[1] * cm + w[2] * dm + w[3] < best.score) {
- break;
- }
- var minStart = Math.floor(dMax / step) * j - (k - 1) * j;
- var maxStart = Math.ceil(dMin / step) * j;
- if (minStart <= maxStart) {
- var count = maxStart - minStart;
- for (var i_1 = 0; i_1 <= count; i_1 += 1) {
- var start = minStart + i_1;
- var lMin = start * (step / j);
- var lMax = lMin + step * (k - 1);
- var lStep = step;
- var s = simplicity(q, Q, j, lMin, lMax, lStep);
- var c = coverage(dMin, dMax, lMin, lMax);
- var g = density(k, m, dMin, dMax, lMin, lMax);
- var l = legibility();
- var score = w[0] * s + w[1] * c + w[2] * g + w[3] * l;
- if (score > best.score && (!onlyLoose || (lMin <= dMin && lMax >= dMax))) {
- best.lmin = lMin;
- best.lmax = lMax;
- best.lstep = lStep;
- best.score = score;
- }
- }
- }
- z += 1;
- }
- k += 1;
- }
- }
- j += 1;
- }
- // 处理精度问题,保证这三个数没有精度问题
- var lmax = prettyNumber(best.lmax);
- var lmin = prettyNumber(best.lmin);
- var lstep = prettyNumber(best.lstep);
- // 加 round 是为处理 extended(0.94, 1, 5)
- // 保证生成的 tickCount 没有精度问题
- var tickCount = Math.floor(round((lmax - lmin) / lstep)) + 1;
- var ticks = new Array(tickCount);
- // 少用乘法:防止出现 -1.2 + 1.2 * 3 = 2.3999999999999995 的情况
- ticks[0] = prettyNumber(lmin);
- for (var i = 1; i < tickCount; i++) {
- ticks[i] = prettyNumber(ticks[i - 1] + lstep);
- }
- return {
- min: Math.min(dMin, head(ticks)),
- max: Math.max(dMax, last(ticks)),
- ticks: ticks,
- };
- }
- /**
- * 计算分类 ticks
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function calculateCatTicks(cfg) {
- var values = cfg.values, tickInterval = cfg.tickInterval, tickCount = cfg.tickCount;
- var ticks = values;
- if (isNumber(tickInterval)) {
- return filter(ticks, function (__, i) { return i % tickInterval === 0; });
- }
- var min = cfg.min, max = cfg.max;
- if (isNil(min)) {
- min = 0;
- }
- if (isNil(max)) {
- max = values.length - 1;
- }
- if (isNumber(tickCount) && tickCount < max - min) {
- // 简单过滤,部分情况下小数的倍数也可以是整数
- // tslint:disable-next-line: no-shadowed-variable
- var ticks_1 = extended(min, max, tickCount, false, [1, 2, 5, 3, 4, 7, 6, 8, 9]).ticks;
- var valid = filter(ticks_1, function (tick) { return tick >= min && tick <= max; });
- return valid.map(function (index) { return values[index]; });
- }
- return values.slice(min, max + 1);
- }
- function d3Linear(cfg) {
- var min = cfg.min, max = cfg.max, nice = cfg.nice, tickCount = cfg.tickCount;
- var linear = new D3Linear();
- linear.domain([min, max]);
- if (nice) {
- linear.nice(tickCount);
- }
- return linear.ticks(tickCount);
- }
- var DEFAULT_COUNT = 5;
- var e10 = Math.sqrt(50);
- var e5 = Math.sqrt(10);
- var e2 = Math.sqrt(2);
- // https://github.com/d3/d3-scale
- var D3Linear = /** @class */ (function () {
- function D3Linear() {
- this._domain = [0, 1];
- }
- D3Linear.prototype.domain = function (domain) {
- if (domain) {
- this._domain = Array.from(domain, Number);
- return this;
- }
- return this._domain.slice();
- };
- D3Linear.prototype.nice = function (count) {
- var _a, _b;
- if (count === void 0) { count = DEFAULT_COUNT; }
- var d = this._domain.slice();
- var i0 = 0;
- var i1 = this._domain.length - 1;
- var start = this._domain[i0];
- var stop = this._domain[i1];
- var step;
- if (stop < start) {
- _a = [stop, start], start = _a[0], stop = _a[1];
- _b = [i1, i0], i0 = _b[0], i1 = _b[1];
- }
- step = tickIncrement(start, stop, count);
- if (step > 0) {
- start = Math.floor(start / step) * step;
- stop = Math.ceil(stop / step) * step;
- step = tickIncrement(start, stop, count);
- }
- else if (step < 0) {
- start = Math.ceil(start * step) / step;
- stop = Math.floor(stop * step) / step;
- step = tickIncrement(start, stop, count);
- }
- if (step > 0) {
- d[i0] = Math.floor(start / step) * step;
- d[i1] = Math.ceil(stop / step) * step;
- this.domain(d);
- }
- else if (step < 0) {
- d[i0] = Math.ceil(start * step) / step;
- d[i1] = Math.floor(stop * step) / step;
- this.domain(d);
- }
- return this;
- };
- D3Linear.prototype.ticks = function (count) {
- if (count === void 0) { count = DEFAULT_COUNT; }
- return d3ArrayTicks(this._domain[0], this._domain[this._domain.length - 1], count || DEFAULT_COUNT);
- };
- return D3Linear;
- }());
- function d3ArrayTicks(start, stop, count) {
- var reverse;
- var i = -1;
- var n;
- var ticks;
- var step;
- (stop = +stop), (start = +start), (count = +count);
- if (start === stop && count > 0) {
- return [start];
- }
- // tslint:disable-next-line
- if ((reverse = stop < start)) {
- (n = start), (start = stop), (stop = n);
- }
- // tslint:disable-next-line
- if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) {
- return [];
- }
- if (step > 0) {
- start = Math.ceil(start / step);
- stop = Math.floor(stop / step);
- ticks = new Array((n = Math.ceil(stop - start + 1)));
- while (++i < n) {
- ticks[i] = (start + i) * step;
- }
- }
- else {
- start = Math.floor(start * step);
- stop = Math.ceil(stop * step);
- ticks = new Array((n = Math.ceil(start - stop + 1)));
- while (++i < n) {
- ticks[i] = (start - i) / step;
- }
- }
- if (reverse) {
- ticks.reverse();
- }
- return ticks;
- }
- function tickIncrement(start, stop, count) {
- var step = (stop - start) / Math.max(0, count);
- var power = Math.floor(Math.log(step) / Math.LN10);
- var error = step / Math.pow(10, power);
- return power >= 0
- ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
- : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
- }
- function snapMultiple(v, base, snapType) {
- var div;
- if (snapType === 'ceil') {
- div = Math.ceil(v / base);
- }
- else if (snapType === 'floor') {
- div = Math.floor(v / base);
- }
- else {
- div = Math.round(v / base);
- }
- return div * base;
- }
- function intervalTicks(min, max, interval) {
- // 变成 interval 的倍数
- var minTick = snapMultiple(min, interval, 'floor');
- var maxTick = snapMultiple(max, interval, 'ceil');
- // 统一小数位数
- minTick = fixedBase(minTick, interval);
- maxTick = fixedBase(maxTick, interval);
- var ticks = [];
- for (var i = minTick; i <= maxTick; i = i + interval) {
- var tickValue = fixedBase(i, interval); // 防止浮点数加法出现问题
- ticks.push(tickValue);
- }
- return {
- min: minTick,
- max: maxTick,
- ticks: ticks
- };
- }
- /**
- * 按照给定的 minLimit/maxLimit/tickCount 均匀计算出刻度 ticks
- *
- * @param cfg Scale 配置项
- * @return ticks
- */
- function strictLimit(cfg, defaultMin, defaultMax) {
- var _a;
- var minLimit = cfg.minLimit, maxLimit = cfg.maxLimit, min = cfg.min, max = cfg.max, _b = cfg.tickCount, tickCount = _b === void 0 ? 5 : _b;
- var tickMin = isNil(minLimit) ? (isNil(defaultMin) ? min : defaultMin) : minLimit;
- var tickMax = isNil(maxLimit) ? (isNil(defaultMax) ? max : defaultMax) : maxLimit;
- if (tickMin > tickMax) {
- _a = [tickMin, tickMax], tickMax = _a[0], tickMin = _a[1];
- }
- if (tickCount <= 2) {
- return [tickMin, tickMax];
- }
- var step = (tickMax - tickMin) / (tickCount - 1);
- var ticks = [];
- for (var i = 0; i < tickCount; i++) {
- ticks.push(tickMin + step * i);
- }
- return ticks;
- }
- function d3LinearTickMethod(cfg) {
- var min = cfg.min, max = cfg.max, tickInterval = cfg.tickInterval, minLimit = cfg.minLimit, maxLimit = cfg.maxLimit;
- var ticks = d3Linear(cfg);
- if (!isNil(minLimit) || !isNil(maxLimit)) {
- return strictLimit(cfg, head(ticks), last(ticks));
- }
- if (tickInterval) {
- return intervalTicks(min, max, tickInterval).ticks;
- }
- return ticks;
- }
- /**
- * 计算线性的 ticks,使用 wilkinson extended 方法
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function linear(cfg) {
- var min = cfg.min, max = cfg.max, tickCount = cfg.tickCount, nice = cfg.nice, tickInterval = cfg.tickInterval, minLimit = cfg.minLimit, maxLimit = cfg.maxLimit;
- var ticks = extended(min, max, tickCount, nice).ticks;
- if (!isNil(minLimit) || !isNil(maxLimit)) {
- return strictLimit(cfg, head(ticks), last(ticks));
- }
- if (tickInterval) {
- return intervalTicks(min, max, tickInterval).ticks;
- }
- return ticks;
- }
- /**
- * 计算 log 的 ticks,考虑 min = 0 的场景
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function calculateLogTicks(cfg) {
- var base = cfg.base, tickCount = cfg.tickCount, min = cfg.min, max = cfg.max, values = cfg.values;
- var minTick;
- var maxTick = log(base, max);
- if (min > 0) {
- minTick = Math.floor(log(base, min));
- }
- else {
- var positiveMin = getLogPositiveMin(values, base, max);
- minTick = Math.floor(log(base, positiveMin));
- }
- var count = maxTick - minTick;
- var avg = Math.ceil(count / tickCount);
- var ticks = [];
- for (var i = minTick; i < maxTick + avg; i = i + avg) {
- ticks.push(Math.pow(base, i));
- }
- if (min <= 0) {
- // 最小值 <= 0 时显示 0
- ticks.unshift(0);
- }
- return ticks;
- }
- function pretty(min, max, m) {
- if (m === void 0) { m = 5; }
- if (min === max) {
- return {
- max: max,
- min: min,
- ticks: [min],
- };
- }
- var n = m < 0 ? 0 : Math.round(m);
- if (n === 0)
- return { max: max, min: min, ticks: [] };
- /*
- R pretty:
- https://svn.r-project.org/R/trunk/src/appl/pretty.c
- https://www.rdocumentation.org/packages/base/versions/3.5.2/topics/pretty
- */
- var h = 1.5; // high.u.bias
- var h5 = 0.5 + 1.5 * h; // u5.bias
- // 反正我也不会调参,跳过所有判断步骤
- var d = max - min;
- var c = d / n;
- // 当d非常小的时候触发,但似乎没什么用
- // const min_n = Math.floor(n / 3);
- // const shrink_sml = Math.pow(2, 5);
- // if (Math.log10(d) < -2) {
- // c = (_.max([ Math.abs(max), Math.abs(min) ]) * shrink_sml) / min_n;
- // }
- var base = Math.pow(10, Math.floor(Math.log10(c)));
- var unit = base;
- if (2 * base - c < h * (c - unit)) {
- unit = 2 * base;
- if (5 * base - c < h5 * (c - unit)) {
- unit = 5 * base;
- if (10 * base - c < h * (c - unit)) {
- unit = 10 * base;
- }
- }
- }
- var nu = Math.ceil(max / unit);
- var ns = Math.floor(min / unit);
- var hi = Math.max(nu * unit, max);
- var lo = Math.min(ns * unit, min);
- var size = Math.floor((hi - lo) / unit) + 1;
- var ticks = new Array(size);
- for (var i = 0; i < size; i++) {
- ticks[i] = prettyNumber(lo + i * unit);
- }
- return {
- min: lo,
- max: hi,
- ticks: ticks,
- };
- }
- /**
- * 计算 Pow 的 ticks
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function calculatePowTicks(cfg) {
- var exponent = cfg.exponent, tickCount = cfg.tickCount;
- var max = Math.ceil(calBase(exponent, cfg.max));
- var min = Math.floor(calBase(exponent, cfg.min));
- var ticks = pretty(min, max, tickCount).ticks;
- return ticks.map(function (tick) {
- var factor = tick >= 0 ? 1 : -1;
- return Math.pow(tick, exponent) * factor;
- });
- }
- /**
- * 计算几分位 https://github.com/simple-statistics/simple-statistics/blob/master/src/quantile_sorted.js
- * @param x 数组
- * @param p 百分比
- */
- function quantileSorted(x, p) {
- var idx = x.length * p;
- /*if (x.length === 0) { // 当前场景这些条件不可能命中
- throw new Error('quantile requires at least one value.');
- } else if (p < 0 || p > 1) {
- throw new Error('quantiles must be between 0 and 1');
- } else */
- if (p === 1) {
- // If p is 1, directly return the last element
- return x[x.length - 1];
- }
- else if (p === 0) {
- // If p is 0, directly return the first element
- return x[0];
- }
- else if (idx % 1 !== 0) {
- // If p is not integer, return the next element in array
- return x[Math.ceil(idx) - 1];
- }
- else if (x.length % 2 === 0) {
- // If the list has even-length, we'll take the average of this number
- // and the next value, if there is one
- return (x[idx - 1] + x[idx]) / 2;
- }
- else {
- // Finally, in the simple case of an integer value
- // with an odd-length list, return the x value at the index.
- return x[idx];
- }
- }
- function calculateTicks(cfg) {
- var tickCount = cfg.tickCount, values = cfg.values;
- if (!values || !values.length) {
- return [];
- }
- var sorted = values.slice().sort(function (a, b) {
- return a - b;
- });
- var ticks = [];
- for (var i = 0; i < tickCount; i++) {
- var p = i / (tickCount - 1);
- ticks.push(quantileSorted(sorted, p));
- }
- return ticks;
- }
- /**
- * 计算线性的 ticks,使用 R's pretty 方法
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function linearPretty(cfg) {
- var min = cfg.min, max = cfg.max, tickCount = cfg.tickCount, tickInterval = cfg.tickInterval, minLimit = cfg.minLimit, maxLimit = cfg.maxLimit;
- var ticks = pretty(min, max, tickCount).ticks;
- if (!isNil(minLimit) || !isNil(maxLimit)) {
- return strictLimit(cfg, head(ticks), last(ticks));
- }
- if (tickInterval) {
- return intervalTicks(min, max, tickInterval).ticks;
- }
- return ticks;
- }
- function calculateTimeTicks(cfg) {
- var min = cfg.min, max = cfg.max, minTickInterval = cfg.minTickInterval;
- var tickInterval = cfg.tickInterval;
- var tickCount = cfg.tickCount;
- // 指定 tickInterval 后 tickCount 不生效,需要重新计算
- if (tickInterval) {
- tickCount = Math.ceil((max - min) / tickInterval);
- }
- else {
- tickInterval = getTickInterval(min, max, tickCount)[1];
- var count = (max - min) / tickInterval;
- var ratio = count / tickCount;
- if (ratio > 1) {
- tickInterval = tickInterval * Math.ceil(ratio);
- }
- // 如果设置了最小间距,则使用最小间距
- if (minTickInterval && tickInterval < minTickInterval) {
- tickInterval = minTickInterval;
- }
- }
- var ticks = [];
- for (var i = min; i < max + tickInterval; i += tickInterval) {
- ticks.push(i);
- }
- return ticks;
- }
- /**
- * 计算时间分类的 ticks, 保头,保尾
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function calculateTimeCatTicks(cfg) {
- var ticks = calculateCatTicks(cfg);
- var lastValue = last(cfg.values);
- if (lastValue !== last(ticks)) {
- ticks.push(lastValue);
- }
- return ticks;
- }
- function getYear(date) {
- return new Date(date).getFullYear();
- }
- function createYear(year) {
- return new Date(year, 0, 1).getTime();
- }
- function getMonth(date) {
- return new Date(date).getMonth();
- }
- function diffMonth(min, max) {
- var minYear = getYear(min);
- var maxYear = getYear(max);
- var minMonth = getMonth(min);
- var maxMonth = getMonth(max);
- return (maxYear - minYear) * 12 + ((maxMonth - minMonth) % 12);
- }
- function creatMonth(year, month) {
- return new Date(year, month, 1).getTime();
- }
- function diffDay(min, max) {
- return Math.ceil((max - min) / DAY);
- }
- function diffHour(min, max) {
- return Math.ceil((max - min) / HOUR);
- }
- function diffMinus(min, max) {
- return Math.ceil((max - min) / (60 * 1000));
- }
- /**
- * 计算 time 的 ticks,对 month, year 进行 pretty 处理
- * @param cfg 度量的配置项
- * @returns 计算后的 ticks
- */
- function timePretty(cfg) {
- var min = cfg.min, max = cfg.max, minTickInterval = cfg.minTickInterval, tickCount = cfg.tickCount;
- var tickInterval = cfg.tickInterval;
- var ticks = [];
- // 指定 tickInterval 后 tickCount 不生效,需要重新计算
- if (!tickInterval) {
- tickInterval = (max - min) / tickCount;
- // 如果设置了最小间距,则使用最小间距
- if (minTickInterval && tickInterval < minTickInterval) {
- tickInterval = minTickInterval;
- }
- }
- var minYear = getYear(min);
- // 如果间距大于 1 年,则将开始日期从整年开始
- if (tickInterval > YEAR) {
- var maxYear = getYear(max);
- var yearInterval = Math.ceil(tickInterval / YEAR);
- for (var i = minYear; i <= maxYear + yearInterval; i = i + yearInterval) {
- ticks.push(createYear(i));
- }
- }
- else if (tickInterval > MONTH) {
- // 大于月时
- var monthInterval = Math.ceil(tickInterval / MONTH);
- var mmMoth = getMonth(min);
- var dMonths = diffMonth(min, max);
- for (var i = 0; i <= dMonths + monthInterval; i = i + monthInterval) {
- ticks.push(creatMonth(minYear, i + mmMoth));
- }
- }
- else if (tickInterval > DAY) {
- // 大于天
- var date = new Date(min);
- var year = date.getFullYear();
- var month = date.getMonth();
- var mday = date.getDate();
- var day = Math.ceil(tickInterval / DAY);
- var ddays = diffDay(min, max);
- for (var i = 0; i < ddays + day; i = i + day) {
- ticks.push(new Date(year, month, mday + i).getTime());
- }
- }
- else if (tickInterval > HOUR) {
- // 大于小时
- var date = new Date(min);
- var year = date.getFullYear();
- var month = date.getMonth();
- var day = date.getDate();
- var hour = date.getHours();
- var hours = Math.ceil(tickInterval / HOUR);
- var dHours = diffHour(min, max);
- for (var i = 0; i <= dHours + hours; i = i + hours) {
- ticks.push(new Date(year, month, day, hour + i).getTime());
- }
- }
- else if (tickInterval > MINUTE) {
- // 大于分钟
- var dMinus = diffMinus(min, max);
- var minutes = Math.ceil(tickInterval / MINUTE);
- for (var i = 0; i <= dMinus + minutes; i = i + minutes) {
- ticks.push(min + i * MINUTE);
- }
- }
- else {
- // 小于分钟
- var interval = tickInterval;
- if (interval < SECOND) {
- interval = SECOND;
- }
- var minSecond = Math.floor(min / SECOND) * SECOND;
- var dSeconds = Math.ceil((max - min) / SECOND);
- var seconds = Math.ceil(interval / SECOND);
- for (var i = 0; i < dSeconds + seconds; i = i + seconds) {
- ticks.push(minSecond + i * SECOND);
- }
- }
- // 最好是能从算法能解决这个问题,但是如果指定了 tickInterval,计算 ticks,也只能这么算,所以
- // 打印警告提示
- if (ticks.length >= 512) {
- console.warn("Notice: current ticks length(" + ticks.length + ") >= 512, may cause performance issues, even out of memory. Because of the configure \"tickInterval\"(in milliseconds, current is " + tickInterval + ") is too small, increase the value to solve the problem!");
- }
- return ticks;
- }
- registerTickMethod('cat', calculateCatTicks);
- registerTickMethod('time-cat', calculateTimeCatTicks);
- registerTickMethod('wilkinson-extended', linear);
- registerTickMethod('r-pretty', linearPretty);
- registerTickMethod('time', calculateTimeTicks);
- registerTickMethod('time-pretty', timePretty);
- registerTickMethod('log', calculateLogTicks);
- registerTickMethod('pow', calculatePowTicks);
- registerTickMethod('quantile', calculateTicks);
- registerTickMethod('d3-linear', d3LinearTickMethod);
- registerClass('cat', Category);
- registerClass('category', Category);
- registerClass('identity', Identity);
- registerClass('linear', Linear);
- registerClass('log', Log);
- registerClass('pow', Pow);
- registerClass('time', Time);
- registerClass('timeCat', TimeCat);
- registerClass('quantize', Quantize);
- registerClass('quantile', Quantile);
- // cat平均算法,保头保尾
- var CatTick = (function (cfg) {
- var {
- values,
- tickCount
- } = cfg;
- if (!tickCount) {
- return values;
- }
- if (values.length <= 1) {
- return values;
- } // 获取间隔步长, 最小是1
- var step = parseInt(values.length / (tickCount - 1)) || 1;
- var ticks = []; // 按间隔数取对应节点
- for (var index = 0; index < values.length; index = index + step) {
- ticks.push(values[index]);
- }
- var last = values[values.length - 1]; // 如果最后一个tick不等于原数据的最后一个
- if (ticks[ticks.length - 1] !== last) {
- if (ticks.length >= tickCount) {
- // 如果当前的tick个数满足要求
- ticks[ticks.length - 1] = last;
- } else {
- // 不满足tickCount则直接加入最后一个
- ticks.push(last);
- }
- }
- return ticks;
- });
- // 认为是nice的刻度
- var SNAP_COUNT_ARRAY = [1, 1.2, 1.5, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10];
- var DEFAULT_COUNT$1 = 5; // 默认刻度值
- var LinearTick = (function (cfg) {
- var {
- tickCount,
- tickInterval
- } = cfg || {};
- var {
- min,
- max
- } = cfg || {};
- min = isNaN(min) ? 0 : min;
- max = isNaN(max) ? 0 : max;
- var count = tickCount && tickCount >= 2 ? tickCount : DEFAULT_COUNT$1; // 计算interval, 优先取tickInterval
- var interval = tickInterval || getBestInterval({
- tickCount: count,
- max,
- min
- }); // 通过interval计算最小tick
- var minTick = Math.floor(min / interval) * interval; // 如果指定了tickInterval, count 需要根据指定的tickInterval来算计
- if (tickInterval) {
- var intervalCount = Math.abs(Math.ceil((max - minTick) / tickInterval)) + 1; // tickCount 作为最小 count 处理
- count = Math.max(count, intervalCount);
- }
- var ticks = [];
- var tickLength = 0;
- var fixedLength = getFixedLength(interval);
- while (tickLength < count) {
- ticks.push(toFixed(minTick + tickLength * interval, fixedLength));
- tickLength++;
- }
- return ticks;
- });
- var DECIMAL_LENGTH = 12;
- function getFactor(number) {
- // 取正数
- number = Math.abs(number);
- var factor = 1;
- if (number === 0) {
- return factor;
- } // 小于1,逐渐放大
- if (number < 1) {
- var count = 0;
- while (number < 1) {
- factor = factor / 10;
- number = number * 10;
- count++;
- } // 浮点数计算出现问题
- if (factor.toString().length > DECIMAL_LENGTH) {
- factor = parseFloat(factor.toFixed(count));
- }
- return factor;
- } // 大于10逐渐缩小
- while (number > 10) {
- factor = factor * 10;
- number = number / 10;
- }
- return factor;
- } // 获取最佳匹配刻度
- function getBestInterval(_ref) {
- var {
- tickCount,
- min,
- max
- } = _ref;
- // 如果最大最小相等,则直接按1处理
- if (min === max) {
- return 1 * getFactor(max);
- } // 1.计算平均刻度间隔
- var avgInterval = (max - min) / (tickCount - 1); // 2.数据标准归一化 映射到[1-10]区间
- var factor = getFactor(avgInterval);
- var calInterval = avgInterval / factor;
- var calMax = max / factor;
- var calMin = min / factor; // 根据平均值推算最逼近刻度值
- var similarityIndex = 0;
- for (var index = 0; index < SNAP_COUNT_ARRAY.length; index++) {
- var item = SNAP_COUNT_ARRAY[index];
- if (calInterval <= item) {
- similarityIndex = index;
- break;
- }
- }
- var similarityInterval = getInterval(similarityIndex, tickCount, calMin, calMax); // 小数点位数还原到数据的位数, 因为similarityIndex有可能是小数,所以需要保留similarityIndex自己的小数位数
- var fixedLength = getFixedLength(similarityInterval) + getFixedLength(factor);
- return toFixed(similarityInterval * factor, fixedLength);
- }
- function getInterval(startIndex, tickCount, min, max) {
- var verify = false;
- var interval = SNAP_COUNT_ARRAY[startIndex]; // 刻度值校验,如果不满足,循环下去
- for (var i = startIndex; i < SNAP_COUNT_ARRAY.length; i++) {
- if (intervalIsVerify({
- interval: SNAP_COUNT_ARRAY[i],
- tickCount,
- max,
- min
- })) {
- // 有符合条件的interval
- interval = SNAP_COUNT_ARRAY[i];
- verify = true;
- break;
- }
- } // 如果不满足, 依次缩小10倍,再计算
- if (!verify) {
- return 10 * getInterval(0, tickCount, min / 10, max / 10);
- }
- return interval;
- } // 刻度是否满足展示需求
- function intervalIsVerify(_ref2) {
- var {
- interval,
- tickCount,
- max,
- min
- } = _ref2;
- var minTick = Math.floor(min / interval) * interval;
- if (minTick + (tickCount - 1) * interval >= max) {
- return true;
- }
- return false;
- } // 计算小数点应该保留的位数
- function getFixedLength(num) {
- var str = num.toString();
- var index = str.indexOf('.');
- var indexOfExp = str.indexOf('e-');
- var length = indexOfExp >= 0 ? parseInt(str.substr(indexOfExp + 2), 10) : str.substr(index + 1).length;
- if (length > 20) {
- // 最多保留20位小数
- length = 20;
- }
- return length;
- } // @antv/util fixedbase不支持科学计数法的判断,需要提mr
- function toFixed(v, length) {
- return parseFloat(v.toFixed(length));
- }
- var Linear$1 = getClass('linear');
- var Identity$1 = getClass('identity');
- var Category$1 = getClass('category');
- var TimeCat$1 = getClass('timeCat'); // 覆盖0.3.x的 cat 方法
- registerTickMethod('cat', CatTick);
- registerTickMethod('time-cat', CatTick); // 覆盖linear 度量的tick算法
- registerTickMethod('wilkinson-extended', LinearTick);
- Scale.Linear = Linear$1;
- Scale.Identity = Identity$1;
- Scale.Category = Category$1;
- Scale.Cat = Category$1;
- Scale.TimeCat = TimeCat$1;
- function isFullCircle(coord) {
- if (!coord.isPolar) {
- return false;
- }
- var startAngle = coord.startAngle;
- var endAngle = coord.endAngle;
- if (!isNil(startAngle) && !isNil(endAngle) && endAngle - startAngle < Math.PI * 2) {
- return false;
- }
- return true;
- }
- function clearObj(obj) {
- Object.keys(obj).forEach(function (key) {
- delete obj[key];
- });
- }
- class ScaleController {
- constructor(cfg) {
- // defs 列定义
- this.defs = {}; // 已经实例化的scale
- this.scales = {};
- mix(this, cfg);
- }
- setFieldDef(field, cfg) {
- var {
- defs
- } = this;
- if (isObject(field)) {
- mix(defs, field);
- } else {
- defs[field] = cfg;
- } // 因为可能同时变更多个scale,所以要把所有已实例化的scale都更新下
- this.updateScales();
- }
- _getDef(field) {
- var defs = this.defs;
- var def = null;
- if (Global.scales[field] || defs[field]) {
- def = mix({}, Global.scales[field]);
- each(defs[field], function (v, k) {
- if (isNil(v)) {
- delete def[k];
- } else {
- def[k] = v;
- }
- });
- }
- return def;
- }
- _getDefaultType(field, data, def) {
- if (def && def.type) {
- return def.type;
- }
- var type = 'linear';
- var value = firstValue$1(data, field);
- if (isArray(value)) {
- value = value[0];
- }
- if (isString(value)) {
- type = 'cat';
- }
- return type;
- }
- _getScaleDef(type, field, data, def) {
- var values;
- if (def && def.values) {
- values = def.values;
- } else {
- values = values$1(data, field);
- }
- var cfg = {
- field,
- values
- };
- if (type !== 'cat' && type !== 'timeCat') {
- if (!def || !(def.min && def.max)) {
- var {
- min,
- max
- } = getRange$1(values);
- cfg.min = min;
- cfg.max = max;
- cfg.nice = true;
- }
- } else {
- cfg.isRounding = false; // used for tickCount calculation
- }
- return cfg;
- } // 调整range,为了让图形居中
- _adjustRange(type, cfg) {
- var {
- range,
- values
- } = cfg; // 如果是线性, 或者有自定义range都不处理
- if (type === 'linear' || range || !values) {
- return cfg;
- }
- var count = values.length; // 单只有一条数据时,在中间显示
- if (count === 1) {
- cfg.range = [0.5, 1];
- } else {
- var {
- chart
- } = this;
- var coord = chart.get('coord');
- var widthRatio = Global.widthRatio.multiplePie;
- var offset = 0;
- if (isFullCircle(coord)) {
- if (!coord.transposed) {
- cfg.range = [0, 1 - 1 / count];
- } else {
- offset = 1 / count * widthRatio;
- cfg.range = [offset / 2, 1 - offset / 2];
- }
- } else {
- // 为了让图形居中,所以才设置range
- offset = 1 / count * 0.5; // 这里可能用0.25会更合理
- cfg.range = [offset, 1 - offset];
- }
- }
- return cfg;
- }
- _getScaleCfg(field, data) {
- var self = this;
- var def = self._getDef(field);
- if (!data || !data.length) {
- if (def && def.type) {
- def.field = field;
- return {
- type: def.type,
- cfg: def
- };
- }
- return {
- type: 'identity',
- cfg: {
- value: field,
- field: field.toString(),
- values: [field]
- }
- };
- }
- var firstObj = data[0];
- var firstValue = firstObj[field];
- if (firstValue === null) {
- firstValue = firstValue$1(data, field);
- }
- if (isNumber(field) || isNil(firstValue) && !def) {
- return {
- type: 'identity',
- cfg: {
- value: field,
- field: field.toString(),
- values: [field]
- }
- };
- }
- var type = self._getDefaultType(field, data, def);
- var cfg = self._getScaleDef(type, field, data, def);
- def && mix(cfg, def);
- cfg = this._adjustRange(type, cfg);
- return {
- type,
- cfg
- };
- }
- createScale(field, data) {
- var {
- scales
- } = this;
- var {
- type,
- cfg
- } = this._getScaleCfg(field, data);
- var scale = scales[field]; // 如果已经存在,且类型相等时直接返回
- if (scale && scale.type === type) {
- scale.change(cfg);
- return scale;
- }
- var Scale = getClass(type);
- var newScale = new Scale(cfg);
- scales[field] = newScale;
- return newScale;
- }
- _updateScale(scale) {
- var {
- field
- } = scale; // 因为每个field的数据都会不同
- var data = this.chart._getScaleData(field);
- var {
- cfg
- } = this._getScaleCfg(field, data);
- scale.change(cfg);
- }
- updateScales() {
- var _this = this;
- var {
- scales
- } = this; // 修改完列定义后,需要更新已经实例化的scale
- // 如果是还没有实例化的,在geom初始化的时候会被实例化,所以这里可以不用更新
- each(scales, function (scale) {
- _this._updateScale(scale);
- });
- } // 调整scale从0开始
- adjustStartZero(scale) {
- var {
- defs
- } = this;
- var {
- field,
- min,
- max
- } = scale; // 如果有定义,则不处理
- if (defs[field] && defs[field].min) {
- return;
- }
- if (min > 0) {
- scale.change({
- min: 0
- });
- } else if (max < 0) {
- scale.change({
- max: 0
- });
- }
- }
- clear() {
- // this.defs = {};
- // this.scales = {};
- clearObj(this.defs);
- clearObj(this.scales);
- this.data = null;
- }
- }
- class Abastract {
- _initDefaultCfg() {
- /**
- * ticks
- * @type {Array}
- */
- this.ticks = [];
- /**
- * the configuration for tickLine
- * @type {Object}
- */
- this.tickLine = {};
- /**
- * the direction of ticks, 1 means clockwise
- * @type {Number}
- */
- this.offsetFactor = 1;
- /**
- * the top container
- * @type {container}
- */
- this.frontContainer = null;
- /**
- * the back container
- * @type {[type]}
- */
- this.backContainer = null;
- /**
- * points for draw grid line
- * @type {Array}
- */
- this.gridPoints = [];
- }
- constructor(cfg) {
- this._initDefaultCfg();
- mix(this, cfg);
- this.draw();
- }
- draw() {
- var {
- line,
- tickLine,
- label,
- grid
- } = this;
- grid && this.drawGrid(grid); // draw the grid lines
- tickLine && this.drawTicks(tickLine); // draw the tickLine
- line && this.drawLine(line); // draw axis line
- label && this.drawLabels(); // draw ticks
- }
- drawTicks(tickCfg) {
- var self = this;
- var ticks = self.ticks;
- var length = tickCfg.length;
- var container = self.getContainer(tickCfg.top);
- each(ticks, function (tick) {
- var start = self.getOffsetPoint(tick.value);
- var end = self.getSidePoint(start, length);
- var shape = container.addShape('line', {
- className: 'axis-tick',
- attrs: mix({
- x1: start.x,
- y1: start.y,
- x2: end.x,
- y2: end.y
- }, tickCfg)
- });
- shape._id = self._id + '-ticks';
- });
- }
- drawLabels() {
- var self = this;
- var labelOffset = self.labelOffset;
- var labels = self.labels;
- each(labels, function (labelShape) {
- var container = self.getContainer(labelShape.get('top'));
- var start = self.getOffsetPoint(labelShape.get('value'));
- var {
- x,
- y
- } = self.getSidePoint(start, labelOffset);
- labelShape.attr(mix({
- x,
- y
- }, self.getTextAlignInfo(start, labelOffset), labelShape.get('textStyle')));
- labelShape._id = self._id + '-' + labelShape.attr('text');
- container.add(labelShape);
- });
- }
- drawLine() {}
- drawGrid(grid) {
- var self = this;
- var {
- gridPoints,
- ticks
- } = self;
- var gridCfg = grid;
- var count = gridPoints.length;
- each(gridPoints, function (subPoints, index) {
- if (isFunction(grid)) {
- var tick = ticks[index] || {};
- var executedGrid = grid(tick.text, index, count);
- gridCfg = executedGrid ? mix({}, Global._defaultAxis.grid, executedGrid) : null;
- }
- if (gridCfg) {
- var type = gridCfg.type; // has two types: 'line' and 'arc'
- var points = subPoints.points;
- var container = self.getContainer(gridCfg.top);
- var shape;
- if (type === 'arc') {
- var {
- center,
- startAngle,
- endAngle
- } = self;
- var radius = Vector2.length([points[0].x - center.x, points[0].y - center.y]);
- shape = container.addShape('Arc', {
- className: 'axis-grid',
- attrs: mix({
- x: center.x,
- y: center.y,
- startAngle,
- endAngle,
- r: radius
- }, gridCfg)
- });
- } else {
- shape = container.addShape('Polyline', {
- className: 'axis-grid',
- attrs: mix({
- points
- }, gridCfg)
- });
- }
- shape._id = subPoints._id;
- }
- });
- }
- getOffsetPoint() {}
- getAxisVector() {}
- getOffsetVector(point, offset) {
- var self = this;
- var axisVector = self.getAxisVector(point);
- var normal = Vector2.normalize([], axisVector);
- var factor = self.offsetFactor;
- var verticalVector = [normal[1] * -1 * factor, normal[0] * factor];
- return Vector2.scale([], verticalVector, offset);
- }
- getSidePoint(point, offset) {
- var self = this;
- var offsetVector = self.getOffsetVector(point, offset);
- return {
- x: point.x + offsetVector[0],
- y: point.y + offsetVector[1]
- };
- }
- getTextAlignInfo(point, offset) {
- var self = this;
- var offsetVector = self.getOffsetVector(point, offset);
- var align;
- var baseLine;
- if (offsetVector[0] > 0) {
- align = 'left';
- } else if (offsetVector[0] < 0) {
- align = 'right';
- } else {
- align = 'center';
- }
- if (offsetVector[1] > 0) {
- baseLine = 'top';
- } else if (offsetVector[1] < 0) {
- baseLine = 'bottom';
- } else {
- baseLine = 'middle';
- }
- return {
- textAlign: align,
- textBaseline: baseLine
- };
- }
- getContainer(isTop) {
- var {
- frontContainer,
- backContainer
- } = this;
- return isTop ? frontContainer : backContainer;
- }
- }
- class Line extends Abastract {
- _initDefaultCfg() {
- super._initDefaultCfg();
- this.start = null;
- this.end = null;
- }
- getOffsetPoint(value) {
- var {
- start,
- end
- } = this;
- return {
- x: start.x + (end.x - start.x) * value,
- y: start.y + (end.y - start.y) * value
- };
- }
- getAxisVector() {
- var {
- start,
- end
- } = this;
- return [end.x - start.x, end.y - start.y];
- }
- drawLine(lineCfg) {
- var container = this.getContainer(lineCfg.top);
- var {
- start,
- end
- } = this;
- container.addShape('line', {
- className: 'axis-line',
- attrs: mix({
- x1: start.x,
- y1: start.y,
- x2: end.x,
- y2: end.y
- }, lineCfg)
- });
- }
- }
- Abastract.Line = Line;
- function _defineProperty$1(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- var calcDirection = function calcDirection(start, end) {
- var xDistance = end.x - start.x;
- var yDistance = end.y - start.y; // x 的距离大于y 说明是横向,否则就是纵向
- if (Math.abs(xDistance) > Math.abs(yDistance)) {
- return xDistance > 0 ? 'right' : 'left';
- }
- return yDistance > 0 ? 'down' : 'up';
- }; // 计算2点之间的距离
- var calcDistance = function calcDistance(point1, point2) {
- var xDistance = Math.abs(point2.x - point1.x);
- var yDistance = Math.abs(point2.y - point1.y);
- return Math.sqrt(xDistance * xDistance + yDistance * yDistance);
- };
- var getCenter = function getCenter(point1, point2) {
- var x = point1.x + (point2.x - point1.x) / 2;
- var y = point1.y + (point2.y - point1.y) / 2;
- return {
- x,
- y
- };
- };
- var convertPoints = function convertPoints(ev, canvas) {
- var touches = ev.touches; // 认为是mouse事件
- if (!touches) {
- var point = getRelativePosition({
- x: ev.clientX,
- y: ev.clientY
- }, canvas);
- return [point];
- }
- var points = [];
- var len = touches.length;
- for (var i = 0; i < len; i++) {
- var touch = touches[i]; // x, y: 相对canvas原点的位置,clientX, clientY 相对于可视窗口的位置
- var {
- x,
- y,
- clientX,
- clientY
- } = touch;
- var _point = void 0; // 小程序环境会有x,y
- if (isNumber(x) || isNumber(y)) {
- _point = {
- x,
- y
- };
- } else {
- // 浏览器环境再计算下canvas的相对位置
- _point = getRelativePosition({
- x: clientX,
- y: clientY
- }, canvas);
- }
- points.push(_point);
- }
- return points;
- };
- var PRESS_DELAY = 250;
- class EventController {
- constructor(_ref) {
- var _this = this;
- var {
- canvas,
- el
- } = _ref;
- _defineProperty$1(this, "_click", function (ev) {
- var points = convertPoints(ev, _this.canvas);
- ev.points = points;
- _this.emitEvent('click', ev);
- });
- _defineProperty$1(this, "_start", function (ev) {
- var points = convertPoints(ev, _this.canvas);
- if (!points) {
- return;
- }
- ev.points = points;
- _this.emitEvent('touchstart', ev); // 防止上次的内容没有清理掉,重新reset下
- _this.reset(); // 记录touch start 的时间
- _this.startTime = Date.now(); // 记录touch start 的点
- _this.startPoints = points;
- if (points.length > 1) {
- _this.startDistance = calcDistance(points[0], points[1]);
- _this.center = getCenter(points[0], points[1]);
- } else {
- // 如果touchstart后停顿250ms, 则也触发press事件
- _this.pressTimeout = setTimeout(function () {
- // 这里固定触发press事件
- var eventType = 'press';
- var direction = 'none';
- ev.direction = direction;
- _this.emitStart(eventType, ev);
- _this.emitEvent(eventType, ev);
- _this.eventType = eventType;
- _this.direction = direction;
- }, PRESS_DELAY);
- }
- });
- _defineProperty$1(this, "_move", function (ev) {
- var points = convertPoints(ev, _this.canvas);
- if (!points) return;
- _this.clearPressTimeout();
- ev.points = points;
- _this.emitEvent('touchmove', ev);
- var startPoints = _this.startPoints;
- if (!startPoints) return; // 多指触控
- if (points.length > 1) {
- // touchstart的距离
- var startDistance = _this.startDistance;
- var currentDistance = calcDistance(points[0], points[1]);
- ev.zoom = currentDistance / startDistance;
- ev.center = _this.center; // 触发缩放事件
- _this.emitStart('pinch', ev);
- _this.emitEvent('pinch', ev);
- } else {
- var deltaX = points[0].x - startPoints[0].x;
- var deltaY = points[0].y - startPoints[0].y;
- var direction = _this.direction || calcDirection(startPoints[0], points[0]);
- _this.direction = direction; // 获取press或者pan的事件类型
- // press 按住滑动, pan表示平移
- // 如果start后立刻move,则触发pan, 如果有停顿,则触发press
- var eventType = _this.getEventType(points);
- ev.direction = direction;
- ev.deltaX = deltaX;
- ev.deltaY = deltaY;
- _this.emitStart(eventType, ev);
- _this.emitEvent(eventType, ev); // 记录最后2次move的时间和坐标,为了给swipe事件用
- var prevMoveTime = _this.lastMoveTime;
- var now = Date.now(); // 最后2次的时间间隔一定要大于0,否则swipe没发计算
- if (now - prevMoveTime > 0) {
- _this.prevMoveTime = prevMoveTime;
- _this.prevMovePoints = _this.lastMovePoints;
- _this.lastMoveTime = now;
- _this.lastMovePoints = points;
- }
- }
- });
- _defineProperty$1(this, "_end", function (ev) {
- _this.emitEnd(ev);
- _this.emitEvent('touchend', ev); // swipe事件处理, 在touchend之后触发
- var lastMoveTime = _this.lastMoveTime;
- var now = Date.now(); // 做这个判断是为了最后一次touchmove后到end前,还有一个停顿的过程
- // 100 是拍的一个值,理论这个值会很短,一般不卡顿的话在10ms以内
- if (now - lastMoveTime < 100) {
- var prevMoveTime = _this.prevMoveTime || _this.startTime;
- var intervalTime = lastMoveTime - prevMoveTime; // 时间间隔一定要大于0, 否则计算没意义
- if (intervalTime > 0) {
- var prevMovePoints = _this.prevMovePoints || _this.startPoints;
- var lastMovePoints = _this.lastMovePoints; // move速率
- var velocity = calcDistance(prevMovePoints[0], lastMovePoints[0]) / intervalTime; // 0.3 是参考hammerjs的设置
- if (velocity > 0.3) {
- ev.velocity = velocity;
- ev.direction = calcDirection(prevMovePoints[0], lastMovePoints[0]);
- _this.emitEvent('swipe', ev);
- }
- }
- }
- _this.reset();
- var touches = ev.touches; // 当多指只释放了1指时也会触发end, 这时重新触发一次start
- if (touches && touches.length > 0) {
- _this._start(ev);
- }
- });
- _defineProperty$1(this, "_cancel", function (ev) {
- _this.emitEvent('touchcancel', ev);
- _this.reset();
- });
- // canvasEl
- this.canvas = canvas;
- this.delegateEvent(el); // 用来记录当前触发的事件
- this.processEvent = {};
- }
- delegateEvent(canvasEl) {
- // 代理这几个事件
- canvasEl.addEventListener('click', this._click);
- canvasEl.addEventListener('touchstart', this._start);
- canvasEl.addEventListener('touchmove', this._move);
- canvasEl.addEventListener('touchend', this._end);
- canvasEl.addEventListener('touchcancel', this._cancel);
- }
- emitEvent(type, ev) {
- var canvas = this.canvas;
- canvas.emit(type, ev);
- }
- getEventType(points) {
- var {
- eventType,
- canvas,
- startTime,
- startPoints
- } = this;
- if (eventType) {
- return eventType;
- }
- var type;
- var panEventListeners = canvas.__events.pan; // 如果没有pan事件的监听,默认都是press
- if (!panEventListeners || !panEventListeners.length) {
- type = 'press';
- } else {
- // 如果有pan事件的处理,press则需要停顿250ms, 且移动距离小于10
- var now = Date.now();
- if (now - startTime > PRESS_DELAY && calcDistance(startPoints[0], points[0]) < 10) {
- type = 'press';
- } else {
- type = 'pan';
- }
- }
- this.eventType = type;
- return type;
- }
- enable(eventType) {
- this.processEvent[eventType] = true;
- } // 是否进行中的事件
- isProcess(eventType) {
- return this.processEvent[eventType];
- } // 触发start事件
- emitStart(type, ev) {
- if (this.isProcess(type)) {
- return;
- }
- this.enable(type);
- this.emitEvent("".concat(type, "start"), ev);
- } // 触发end事件
- emitEnd(ev) {
- var _this2 = this;
- var processEvent = this.processEvent;
- Object.keys(processEvent).forEach(function (type) {
- _this2.emitEvent("".concat(type, "end"), ev);
- delete processEvent[type];
- });
- }
- clearPressTimeout() {
- if (this.pressTimeout) {
- clearTimeout(this.pressTimeout);
- this.pressTimeout = 0;
- }
- }
- reset() {
- this.clearPressTimeout();
- this.startTime = 0;
- this.startPoints = null;
- this.startDistance = 0;
- this.direction = null;
- this.eventType = null;
- this.pinch = false;
- this.prevMoveTime = 0;
- this.prevMovePoints = null;
- this.lastMoveTime = 0;
- this.lastMovePoints = null;
- }
- }
- class CanvasElement extends EventEmit {
- constructor(ctx) {
- super();
- this.context = ctx; // canvas实际的宽高 (width/height) * pixelRatio
- this.width = 0;
- this.height = 0;
- this.style = {};
- this.currentStyle = {}; // 用来标识是CanvasElement实例
- this.isCanvasElement = true;
- }
- getContext()
- /* type */
- {
- return this.context;
- }
- getBoundingClientRect() {
- var width = this.width;
- var height = this.height; // 默认都处理成可视窗口的顶部位置
- return {
- top: 0,
- right: width,
- bottom: height,
- left: 0
- };
- }
- addEventListener(type, listener) {
- this.on(type, listener);
- }
- removeEventListener(type, listener) {
- this.off(type, listener);
- }
- dispatchEvent(type, e) {
- this.emit(type, e);
- }
- }
- function supportEventListener(canvas) {
- if (!canvas) {
- return false;
- } // 非 HTMLCanvasElement
- if (canvas.nodeType !== 1 || !canvas.nodeName || canvas.nodeName.toLowerCase() !== 'canvas') {
- return false;
- } // 微信小程序canvas.getContext('2d')时也是CanvasRenderingContext2D
- // 也会有ctx.canvas, 而且nodeType也是1,所以还要在看下是否支持addEventListener
- var support = false;
- try {
- canvas.addEventListener('eventTest', function () {
- support = true;
- });
- canvas.dispatchEvent(new Event('eventTest'));
- } catch (error) {
- support = false;
- }
- return support;
- }
- var CanvasElement$1 = {
- create(ctx) {
- if (!ctx) {
- return null;
- }
- if (supportEventListener(ctx.canvas)) {
- return ctx.canvas;
- }
- return new CanvasElement(ctx);
- }
- };
- function _mod(n, m) {
- return (n % m + m) % m;
- }
- function _addStop(steps, gradient) {
- each(steps, function (item) {
- item = item.split(':');
- gradient.addColorStop(Number(item[0]), item[1]);
- });
- } // the string format: 'l(0) 0:#ffffff 0.5:#7ec2f3 1:#1890ff'
- function _parseLineGradient(color, shape, context) {
- var arr = color.split(' ');
- var angle = arr[0].slice(2, arr[0].length - 1);
- angle = _mod(parseFloat(angle) * Math.PI / 180, Math.PI * 2);
- var steps = arr.slice(1);
- var {
- minX,
- minY,
- maxX,
- maxY
- } = shape.getBBox();
- var start;
- var end;
- if (angle >= 0 && angle < 0.5 * Math.PI) {
- start = {
- x: minX,
- y: minY
- };
- end = {
- x: maxX,
- y: maxY
- };
- } else if (0.5 * Math.PI <= angle && angle < Math.PI) {
- start = {
- x: maxX,
- y: minY
- };
- end = {
- x: minX,
- y: maxY
- };
- } else if (Math.PI <= angle && angle < 1.5 * Math.PI) {
- start = {
- x: maxX,
- y: maxY
- };
- end = {
- x: minX,
- y: minY
- };
- } else {
- start = {
- x: minX,
- y: maxY
- };
- end = {
- x: maxX,
- y: minY
- };
- }
- var tanTheta = Math.tan(angle);
- var tanTheta2 = tanTheta * tanTheta;
- var x = (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.x;
- var y = tanTheta * (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.y;
- var gradient = context.createLinearGradient(start.x, start.y, x, y);
- _addStop(steps, gradient);
- return gradient;
- } // the string format: 'r(0.5, 0.5, 0.1) 0:#ffffff 1:#1890ff'
- function _parseRadialGradient(color, shape, context) {
- var arr = color.split(' ');
- var circleCfg = arr[0].slice(2, arr[0].length - 1);
- circleCfg = circleCfg.split(',');
- var fx = parseFloat(circleCfg[0]);
- var fy = parseFloat(circleCfg[1]);
- var fr = parseFloat(circleCfg[2]);
- var steps = arr.slice(1); // if radius is 0, no gradient, stroke with the last color
- if (fr === 0) {
- var _color = steps[steps.length - 1];
- return _color.split(':')[1];
- }
- var {
- width,
- height,
- minX,
- minY
- } = shape.getBBox();
- var r = Math.sqrt(width * width + height * height) / 2;
- var gradient = context.createRadialGradient(minX + width * fx, minY + height * fy, fr * r, minX + width / 2, minY + height / 2, r);
- _addStop(steps, gradient);
- return gradient;
- }
- function parseStyle(color, shape, context) {
- if (color[1] === '(') {
- try {
- var firstCode = color[0];
- if (firstCode === 'l') {
- return _parseLineGradient(color, shape, context);
- } else if (firstCode === 'r') {
- return _parseRadialGradient(color, shape, context);
- }
- } catch (ev) {
- console.error('error in parsing gradient string, please check if there are any extra whitespaces.');
- console.error(ev);
- }
- }
- return color;
- }
- var ALIAS_ATTRS_MAP = {
- stroke: 'strokeStyle',
- fill: 'fillStyle',
- opacity: 'globalAlpha'
- };
- var SHAPE_ATTRS = ['fillStyle', 'font', 'globalAlpha', 'lineCap', 'lineWidth', 'lineJoin', 'miterLimit', 'shadowBlur', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'strokeStyle', 'textAlign', 'textBaseline', 'lineDash', 'shadow' // 兼容支付宝小程序
- ];
- var CLIP_SHAPES = ['circle', 'sector', 'polygon', 'rect', 'polyline'];
- class Element$1 {
- _initProperties() {
- this._attrs = {
- zIndex: 0,
- visible: true,
- destroyed: false
- };
- }
- constructor(cfg) {
- this._initProperties();
- mix(this._attrs, cfg);
- var attrs = this._attrs.attrs;
- if (attrs) {
- this.initAttrs(attrs);
- }
- this.initTransform();
- }
- get(name) {
- return this._attrs[name];
- }
- set(name, value) {
- this._attrs[name] = value;
- }
- isGroup() {
- return this.get('isGroup');
- }
- isShape() {
- return this.get('isShape');
- }
- initAttrs(attrs) {
- this.attr(mix(this.getDefaultAttrs(), attrs));
- }
- getDefaultAttrs() {
- return {};
- }
- _setAttr(name, value) {
- var attrs = this._attrs.attrs;
- if (name === 'clip') {
- value = this._setAttrClip(value);
- } else {
- var alias = ALIAS_ATTRS_MAP[name];
- if (alias) {
- attrs[alias] = value;
- }
- }
- attrs[name] = value;
- }
- _getAttr(name) {
- return this._attrs.attrs[name];
- } // _afterAttrsSet() {}
- _setAttrClip(clip) {
- if (clip && CLIP_SHAPES.indexOf(clip._attrs.type) > -1) {
- if (clip.get('canvas') === null) {
- clip = Object.assign({}, clip);
- }
- clip.set('parent', this.get('parent'));
- clip.set('context', this.get('context'));
- return clip;
- }
- return null;
- }
- attr(name, value) {
- var self = this;
- if (self.get('destroyed')) return null;
- var argumentsLen = arguments.length;
- if (argumentsLen === 0) {
- return self._attrs.attrs;
- }
- if (isObject(name)) {
- this._attrs.bbox = null;
- for (var k in name) {
- self._setAttr(k, name[k]);
- }
- if (self._afterAttrsSet) {
- self._afterAttrsSet();
- }
- return self;
- }
- if (argumentsLen === 2) {
- this._attrs.bbox = null;
- self._setAttr(name, value);
- if (self._afterAttrsSet) {
- self._afterAttrsSet();
- }
- return self;
- }
- return self._getAttr(name);
- }
- getParent() {
- return this.get('parent');
- }
- draw(context) {
- if (this.get('destroyed')) {
- return;
- }
- if (this.get('visible')) {
- this.setContext(context);
- this.drawInner(context);
- this.restoreContext(context);
- }
- }
- setContext(context) {
- var clip = this._attrs.attrs.clip;
- context.save();
- if (clip) {
- clip.resetTransform(context);
- clip.createPath(context);
- context.clip();
- }
- this.resetContext(context);
- this.resetTransform(context);
- }
- restoreContext(context) {
- context.restore();
- }
- resetContext(context) {
- var elAttrs = this._attrs.attrs;
- if (!this._attrs.isGroup) {
- for (var k in elAttrs) {
- if (SHAPE_ATTRS.indexOf(k) > -1) {
- var v = elAttrs[k];
- if (k === 'fillStyle' || k === 'strokeStyle') {
- v = parseStyle(v, this, context);
- }
- if (k === 'lineDash' && context.setLineDash && isArray(v)) {
- context.setLineDash(v);
- } else {
- context[k] = v;
- }
- }
- }
- }
- }
- hasFill() {
- return this.get('canFill') && this._attrs.attrs.fillStyle;
- }
- hasStroke() {
- return this.get('canStroke') && this._attrs.attrs.strokeStyle;
- }
- drawInner()
- /* context */
- {}
- show() {
- this.set('visible', true);
- return this;
- }
- hide() {
- this.set('visible', false);
- return this;
- }
- isVisible() {
- return this.get('visible');
- }
- _removeFromParent() {
- var parent = this.get('parent');
- if (parent) {
- var children = parent.get('children');
- remove$1(children, this);
- }
- return this;
- }
- remove(destroy) {
- if (destroy) {
- this.destroy();
- } else {
- this._removeFromParent();
- }
- }
- destroy() {
- var destroyed = this.get('destroyed');
- if (destroyed) {
- return null;
- }
- this._removeFromParent();
- this._attrs = {};
- this.set('destroyed', true);
- }
- getBBox() {
- return {
- minX: 0,
- maxX: 0,
- minY: 0,
- maxY: 0,
- width: 0,
- height: 0
- };
- }
- initTransform() {
- var attrs = this._attrs.attrs || {};
- if (!attrs.matrix) {
- attrs.matrix = [1, 0, 0, 1, 0, 0];
- }
- this._attrs.attrs = attrs;
- }
- getMatrix() {
- return this._attrs.attrs.matrix;
- }
- setMatrix(m) {
- this._attrs.attrs.matrix = [m[0], m[1], m[2], m[3], m[4], m[5]];
- }
- transform(actions) {
- var matrix = this._attrs.attrs.matrix;
- this._attrs.attrs.matrix = Matrix.transform(matrix, actions);
- return this;
- }
- setTransform(actions) {
- this._attrs.attrs.matrix = [1, 0, 0, 1, 0, 0];
- return this.transform(actions);
- }
- translate(x, y) {
- var matrix = this._attrs.attrs.matrix;
- Matrix.translate(matrix, matrix, [x, y]);
- }
- rotate(rad) {
- var matrix = this._attrs.attrs.matrix;
- Matrix.rotate(matrix, matrix, rad);
- }
- scale(sx, sy) {
- var matrix = this._attrs.attrs.matrix;
- Matrix.scale(matrix, matrix, [sx, sy]);
- }
- moveTo(x, y) {
- var cx = this._attrs.x || 0;
- var cy = this._attrs.y || 0;
- this.translate(x - cx, y - cy);
- this.set('x', x);
- this.set('y', y);
- }
- apply(v) {
- var m = this._attrs.attrs.matrix;
- Vector2.transformMat2d(v, v, m);
- return this;
- }
- resetTransform(context) {
- var mo = this._attrs.attrs.matrix;
- if (Matrix.isChanged(mo)) {
- context.transform(mo[0], mo[1], mo[2], mo[3], mo[4], mo[5]);
- }
- }
- isDestroyed() {
- return this.get('destroyed');
- }
- }
- class Shape$2 extends Element$1 {
- _initProperties() {
- this._attrs = {
- zIndex: 0,
- visible: true,
- destroyed: false,
- isShape: true,
- attrs: {}
- };
- }
- getType() {
- return this._attrs.type;
- }
- drawInner(context) {
- var self = this;
- var attrs = self.get('attrs');
- self.createPath(context);
- var originOpacity = context.globalAlpha;
- if (self.hasFill()) {
- var fillOpacity = attrs.fillOpacity;
- if (!isNil(fillOpacity) && fillOpacity !== 1) {
- context.globalAlpha = fillOpacity;
- context.fill();
- context.globalAlpha = originOpacity;
- } else {
- context.fill();
- }
- }
- if (self.hasStroke()) {
- var lineWidth = attrs.lineWidth;
- if (lineWidth > 0) {
- var strokeOpacity = attrs.strokeOpacity;
- if (!isNil(strokeOpacity) && strokeOpacity !== 1) {
- context.globalAlpha = strokeOpacity;
- }
- context.stroke();
- }
- }
- }
- getBBox() {
- var bbox = this._attrs.bbox;
- if (!bbox) {
- bbox = this.calculateBox();
- if (bbox) {
- bbox.x = bbox.minX;
- bbox.y = bbox.minY;
- bbox.width = bbox.maxX - bbox.minX;
- bbox.height = bbox.maxY - bbox.minY;
- }
- this._attrs.bbox = bbox;
- }
- return bbox;
- }
- calculateBox() {
- return null;
- }
- createPath() {}
- }
- var SHAPE_MAP = {};
- var INDEX = '_INDEX';
- function getComparer(compare) {
- return function (left, right) {
- var result = compare(left, right);
- return result === 0 ? left[INDEX] - right[INDEX] : result;
- };
- }
- var Container = {
- getGroupClass() {},
- getChildren() {
- return this.get('children');
- },
- addShape(type) {
- var cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- var canvas = this.get('canvas');
- var shapeType = SHAPE_MAP[type];
- if (!shapeType) {
- shapeType = upperFirst(type);
- SHAPE_MAP[type] = shapeType;
- }
- cfg.canvas = canvas;
- if (shapeType === 'Text' && canvas && canvas.get('fontFamily')) {
- cfg.attrs.fontFamily = cfg.attrs.fontFamily || canvas.get('fontFamily');
- }
- var shape = new Shape$2[shapeType](cfg);
- this.add(shape);
- return shape;
- },
- addGroup(cfg) {
- var canvas = this.get('canvas');
- var groupClass = this.getGroupClass();
- cfg = mix({}, cfg);
- cfg.canvas = canvas;
- cfg.parent = this;
- var rst = new groupClass(cfg);
- this.add(rst);
- return rst;
- },
- contain(item) {
- var children = this.get('children');
- return children.indexOf(item) > -1;
- },
- sort() {
- var children = this.get('children');
- for (var i = 0, len = children.length; i < len; i++) {
- var child = children[i];
- child[INDEX] = i;
- }
- children.sort(getComparer(function (obj1, obj2) {
- return obj1.get('zIndex') - obj2.get('zIndex');
- }));
- return this;
- },
- drawInner(context) {
- var children = this.get('children');
- for (var i = 0, len = children.length; i < len; i++) {
- var child = children[i];
- child.draw(context);
- }
- return this;
- },
- clear() {
- var children = this.get('children');
- while (children.length !== 0) {
- children[children.length - 1].remove(true);
- }
- return this;
- },
- add(items) {
- var self = this;
- var children = self.get('children');
- if (!isArray(items)) {
- items = [items];
- }
- for (var i = 0, len = items.length; i < len; i++) {
- var item = items[i];
- var parent = item.get('parent');
- if (parent) {
- var descendants = parent.get('children');
- remove$1(descendants, item);
- }
- self._setEvn(item);
- children.push(item);
- }
- return self;
- },
- _setEvn(item) {
- var self = this;
- item._attrs.parent = self;
- item._attrs.context = self._attrs.context;
- item._attrs.canvas = self._attrs.canvas;
- var clip = item._attrs.attrs.clip;
- if (clip) {
- clip.set('parent', self);
- clip.set('context', self.get('context'));
- }
- if (item._attrs.isGroup) {
- var children = item._attrs.children;
- for (var i = 0, len = children.length; i < len; i++) {
- item._setEvn(children[i]);
- }
- }
- }
- };
- class Group extends Element$1 {
- _initProperties() {
- this._attrs = {
- zIndex: 0,
- visible: true,
- destroyed: false,
- isGroup: true,
- children: []
- };
- }
- getBBox() {
- var self = this;
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- var children = self.get('children');
- for (var i = 0, length = children.length; i < length; i++) {
- var child = children[i];
- if (child.get('visible')) {
- var box = child.getBBox();
- if (!box) {
- continue;
- }
- var leftTop = [box.minX, box.minY];
- var leftBottom = [box.minX, box.maxY];
- var rightTop = [box.maxX, box.minY];
- var rightBottom = [box.maxX, box.maxY];
- var matrix = child.attr('matrix');
- Vector2.transformMat2d(leftTop, leftTop, matrix);
- Vector2.transformMat2d(leftBottom, leftBottom, matrix);
- Vector2.transformMat2d(rightTop, rightTop, matrix);
- Vector2.transformMat2d(rightBottom, rightBottom, matrix);
- minX = Math.min(leftTop[0], leftBottom[0], rightTop[0], rightBottom[0], minX);
- maxX = Math.max(leftTop[0], leftBottom[0], rightTop[0], rightBottom[0], maxX);
- minY = Math.min(leftTop[1], leftBottom[1], rightTop[1], rightBottom[1], minY);
- maxY = Math.max(leftTop[1], leftBottom[1], rightTop[1], rightBottom[1], maxY);
- }
- }
- return {
- minX,
- minY,
- maxX,
- maxY,
- x: minX,
- y: minY,
- width: maxX - minX,
- height: maxY - minY
- };
- }
- destroy() {
- if (this.get('destroyed')) {
- return;
- }
- this.clear();
- super.destroy();
- }
- }
- mix(Group.prototype, Container, {
- getGroupClass() {
- return Group;
- }
- });
- var requestAnimationFrame$1 = typeof window === 'object' && window.requestAnimationFrame ? window.requestAnimationFrame : function (fn) {
- return setTimeout(fn, 16);
- };
- class Canvas extends EventEmit {
- get(name) {
- return this._attrs[name];
- }
- set(name, value) {
- this._attrs[name] = value;
- }
- constructor(cfg) {
- super();
- this._attrs = mix({
- type: 'canvas',
- children: []
- }, cfg);
- this._initPixelRatio();
- this._initCanvas();
- }
- _initPixelRatio() {
- var pixelRatio = this.get('pixelRatio');
- if (!pixelRatio) {
- this.set('pixelRatio', getPixelRatio());
- }
- }
- beforeDraw() {
- var context = this._attrs.context;
- var el = this._attrs.el;
- context && context.clearRect && context.clearRect(0, 0, el.width, el.height);
- }
- _initCanvas() {
- var self = this;
- var el = self.get('el');
- var context = self.get('context');
- if (!el && !context) {
- throw new Error('Please specify the id, el or context of the chart!');
- }
- var canvas;
- if (el) {
- // DOMElement or String
- canvas = isString(el) ? getDomById(el) : el;
- } else {
- // 说明没有指定el
- canvas = CanvasElement$1.create(context);
- }
- if (context && canvas && !canvas.getContext) {
- canvas.getContext = function () {
- return context;
- };
- }
- var width = self.get('width');
- if (!width) {
- width = getWidth(canvas);
- }
- var height = self.get('height');
- if (!height) {
- height = getHeight(canvas);
- }
- self.set('canvas', this);
- self.set('el', canvas);
- self.set('context', context || canvas.getContext('2d'));
- self.changeSize(width, height); // 初始化事件控制器
- var eventController = new EventController({
- canvas: this,
- el: canvas
- });
- self.set('eventController', eventController);
- }
- changeSize(width, height) {
- var pixelRatio = this.get('pixelRatio');
- var canvasDOM = this.get('el'); // HTMLCanvasElement or canvasElement
- // 浏览器环境设置style样式
- if (canvasDOM.style) {
- canvasDOM.style.width = width + 'px';
- canvasDOM.style.height = height + 'px';
- }
- if (isCanvasElement(canvasDOM)) {
- canvasDOM.width = width * pixelRatio;
- canvasDOM.height = height * pixelRatio;
- if (pixelRatio !== 1) {
- var ctx = this.get('context');
- ctx.scale(pixelRatio, pixelRatio);
- }
- }
- this.set('width', width);
- this.set('height', height);
- }
- getWidth() {
- var pixelRatio = this.get('pixelRatio');
- var width = this.get('width');
- return width * pixelRatio;
- }
- getHeight() {
- var pixelRatio = this.get('pixelRatio');
- var height = this.get('height');
- return height * pixelRatio;
- }
- getPointByClient(clientX, clientY) {
- var el = this.get('el');
- var bbox = el.getBoundingClientRect();
- var width = bbox.right - bbox.left;
- var height = bbox.bottom - bbox.top;
- return {
- x: (clientX - bbox.left) * (el.width / width),
- y: (clientY - bbox.top) * (el.height / height)
- };
- }
- _beginDraw() {
- this._attrs.toDraw = true;
- }
- _endDraw() {
- this._attrs.toDraw = false;
- }
- draw() {
- var self = this;
- function drawInner() {
- self.set('animateHandler', requestAnimationFrame$1(function () {
- self.set('animateHandler', undefined);
- if (self.get('toDraw')) {
- drawInner();
- }
- }));
- self.beforeDraw();
- try {
- var context = self._attrs.context;
- self.drawInner(context); // 支付宝,微信小程序,需要调context.draw才能完成绘制, 所以这里直接判断是否有.draw方法
- if (context.draw) {
- context.draw();
- }
- } catch (ev) {
- console.warn('error in draw canvas, detail as:');
- console.warn(ev);
- self._endDraw();
- }
- self._endDraw();
- }
- if (self.get('destroyed')) {
- return;
- }
- if (self.get('animateHandler')) {
- this._beginDraw();
- } else {
- drawInner();
- }
- }
- destroy() {
- if (this.get('destroyed')) {
- return;
- } // 需要清理 canvas 画布内容,否则会导致 spa 应用 ios 下 canvas 白屏
- // https://stackoverflow.com/questions/52532614/total-canvas-memory-use-exceeds-the-maximum-limit-safari-12
- // https://github.com/antvis/F2/issues/630
- var el = this.get('el');
- el.width = 0;
- el.height = 0;
- this.clear();
- this._attrs = {};
- this.set('destroyed', true);
- }
- isDestroyed() {
- return this.get('destroyed');
- }
- }
- mix(Canvas.prototype, Container, {
- getGroupClass() {
- return Group;
- }
- });
- function parseRadius$1(radius, width, height) {
- radius = parsePadding(radius); // 都为0
- if (!radius[0] && !radius[1] && !radius[2] && !radius[3]) {
- return radius;
- }
- var minWidth = Math.max(radius[0] + radius[1], radius[2] + radius[3]);
- var minHeight = Math.max(radius[0] + radius[3], radius[1] + radius[2]);
- var scale = Math.min(width / minWidth, height / minHeight);
- if (scale < 1) {
- return radius.map(function (r) {
- return r * scale;
- });
- }
- return radius;
- }
- class Rect extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'rect';
- }
- getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- radius: 0,
- lineWidth: 0
- };
- }
- createPath(context) {
- var self = this;
- var attrs = self.get('attrs');
- var {
- x,
- y,
- width,
- height,
- radius
- } = attrs;
- context.beginPath();
- if (!radius || !(width * height)) {
- context.rect(x, y, width, height);
- } else {
- radius = parseRadius$1(radius, width, height);
- context.moveTo(x + radius[0], y);
- context.lineTo(x + width - radius[1], y);
- context.arc(x + width - radius[1], y + radius[1], radius[1], -Math.PI / 2, 0, false);
- context.lineTo(x + width, y + height - radius[2]);
- context.arc(x + width - radius[2], y + height - radius[2], radius[2], 0, Math.PI / 2, false);
- context.lineTo(x + radius[3], y + height);
- context.arc(x + radius[3], y + height - radius[3], radius[3], Math.PI / 2, Math.PI, false);
- context.lineTo(x, y + radius[0]);
- context.arc(x + radius[0], y + radius[0], radius[0], Math.PI, Math.PI * 3 / 2, false);
- context.closePath();
- }
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- width,
- height
- } = attrs;
- return {
- minX: x,
- minY: y,
- maxX: x + width,
- maxY: y + height
- };
- }
- }
- Shape$2.Rect = Rect;
- class ImageShape extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = false;
- this._attrs.canStroke = false;
- this._attrs.loading = false;
- this._attrs.image = null;
- this._attrs.type = 'image';
- }
- getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- width: 0,
- height: 0
- };
- }
- createPath(context) {
- var _this = this;
- var attrs = this.get('attrs');
- var {
- src
- } = attrs;
- if (this.get('loading')) {
- return;
- }
- var image = this.get('image');
- if (image) {
- this.drawImage(context, image);
- } else {
- if (src && Image) {
- this.set('loading', true);
- var _image = new Image();
- _image.src = src; // 设置跨域
- _image.crossOrigin = 'Anonymous';
- _image.onload = function () {
- _this.set('loading', false);
- _this.set('image', _image);
- _this.drawImage(context, _image);
- };
- }
- }
- }
- drawImage(context, image) {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- width,
- height,
- sx,
- sy,
- swidth,
- sheight
- } = attrs;
- if (!isNil(sx) && !isNil(sy) && !isNil(swidth) && !isNil(sheight)) {
- context.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
- } else {
- context.drawImage(image, x, y, width, height);
- }
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- width,
- height
- } = attrs; // 和rect一样
- return {
- minX: x,
- minY: y,
- maxX: x + width,
- maxY: y + height
- };
- }
- }
- Shape$2.Image = ImageShape;
- class Circle extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'circle';
- }
- getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- r: 0,
- lineWidth: 0
- };
- }
- createPath(context) {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- r
- } = attrs;
- context.beginPath();
- context.arc(x, y, r, 0, Math.PI * 2, false);
- context.closePath();
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- r
- } = attrs;
- return {
- minX: x - r,
- maxX: x + r,
- minY: y - r,
- maxY: y + r
- };
- }
- }
- Shape$2.Circle = Circle;
- var start = Vector2.create();
- var end = Vector2.create();
- var extremity = Vector2.create();
- function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
- var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
- var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
- return {
- x,
- y
- };
- } // cubic helper formula at T distance
- function CubicN(T, a, b, c, d) {
- var t2 = T * T;
- var t3 = t2 * T;
- return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
- }
- function cubicBezierBounds(c) {
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- var s = {
- x: c[0],
- y: c[1]
- };
- var c1 = {
- x: c[2],
- y: c[3]
- };
- var c2 = {
- x: c[4],
- y: c[5]
- };
- var e = {
- x: c[6],
- y: c[7]
- };
- for (var t = 0; t < 100; t++) {
- var pt = getCubicBezierXYatT(s, c1, c2, e, t / 100);
- if (pt.x < minX) {
- minX = pt.x;
- }
- if (pt.x > maxX) {
- maxX = pt.x;
- }
- if (pt.y < minY) {
- minY = pt.y;
- }
- if (pt.y > maxY) {
- maxY = pt.y;
- }
- }
- return {
- minX,
- minY,
- maxX,
- maxY
- };
- }
- function getBBoxFromPoints(points, lineWidth) {
- if (points.length === 0) {
- return;
- }
- var p = points[0];
- var left = p.x;
- var right = p.x;
- var top = p.y;
- var bottom = p.y;
- var len = points.length;
- for (var i = 1; i < len; i++) {
- p = points[i];
- left = Math.min(left, p.x);
- right = Math.max(right, p.x);
- top = Math.min(top, p.y);
- bottom = Math.max(bottom, p.y);
- }
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: left - lineWidth,
- minY: top - lineWidth,
- maxX: right + lineWidth,
- maxY: bottom + lineWidth
- };
- }
- function getBBoxFromLine(x0, y0, x1, y1, lineWidth) {
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: Math.min(x0, x1) - lineWidth,
- minY: Math.min(y0, y1) - lineWidth,
- maxX: Math.max(x0, x1) + lineWidth,
- maxY: Math.max(y0, y1) + lineWidth
- };
- }
- function getBBoxFromArc(x, y, r, startAngle, endAngle, anticlockwise) {
- var diff = Math.abs(startAngle - endAngle);
- if (diff % (Math.PI * 2) < 1e-4 && diff > 1e-4) {
- // Is a circle
- return {
- minX: x - r,
- minY: y - r,
- maxX: x + r,
- maxY: y + r
- };
- }
- start[0] = Math.cos(startAngle) * r + x;
- start[1] = Math.sin(startAngle) * r + y;
- end[0] = Math.cos(endAngle) * r + x;
- end[1] = Math.sin(endAngle) * r + y;
- var min = [0, 0];
- var max = [0, 0];
- Vector2.min(min, start, end);
- Vector2.max(max, start, end); // Thresh to [0, Math.PI * 2]
- startAngle = startAngle % (Math.PI * 2);
- if (startAngle < 0) {
- startAngle = startAngle + Math.PI * 2;
- }
- endAngle = endAngle % (Math.PI * 2);
- if (endAngle < 0) {
- endAngle = endAngle + Math.PI * 2;
- }
- if (startAngle > endAngle && !anticlockwise) {
- endAngle += Math.PI * 2;
- } else if (startAngle < endAngle && anticlockwise) {
- startAngle += Math.PI * 2;
- }
- if (anticlockwise) {
- var tmp = endAngle;
- endAngle = startAngle;
- startAngle = tmp;
- }
- for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
- if (angle > startAngle) {
- extremity[0] = Math.cos(angle) * r + x;
- extremity[1] = Math.sin(angle) * r + y;
- Vector2.min(min, extremity, min);
- Vector2.max(max, extremity, max);
- }
- }
- return {
- minX: min[0],
- minY: min[1],
- maxX: max[0],
- maxY: max[1]
- };
- }
- function getBBoxFromBezierGroup(points, lineWidth) {
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- for (var i = 0, len = points.length; i < len; i++) {
- var bbox = cubicBezierBounds(points[i]);
- if (bbox.minX < minX) {
- minX = bbox.minX;
- }
- if (bbox.maxX > maxX) {
- maxX = bbox.maxX;
- }
- if (bbox.minY < minY) {
- minY = bbox.minY;
- }
- if (bbox.maxY > maxY) {
- maxY = bbox.maxY;
- }
- }
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: minX - lineWidth,
- minY: minY - lineWidth,
- maxX: maxX + lineWidth,
- maxY: maxY + lineWidth
- };
- }
- class Line$1 extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canStroke = true;
- this._attrs.type = 'line';
- }
- getDefaultAttrs() {
- return {
- x1: 0,
- y1: 0,
- x2: 0,
- y2: 0,
- lineWidth: 1
- };
- }
- createPath(context) {
- var attrs = this.get('attrs');
- var {
- x1,
- y1,
- x2,
- y2
- } = attrs;
- context.beginPath();
- context.moveTo(x1, y1);
- context.lineTo(x2, y2);
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x1,
- y1,
- x2,
- y2,
- lineWidth
- } = attrs;
- return getBBoxFromLine(x1, y1, x2, y2, lineWidth);
- }
- }
- Shape$2.Line = Line$1;
- class Polygon extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'polygon';
- }
- getDefaultAttrs() {
- return {
- points: null,
- lineWidth: 0
- };
- }
- createPath(context) {
- var self = this;
- var attrs = self.get('attrs');
- var points = attrs.points;
- context.beginPath();
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- if (i === 0) {
- context.moveTo(point.x, point.y);
- } else {
- context.lineTo(point.x, point.y);
- }
- }
- context.closePath();
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- points
- } = attrs;
- return getBBoxFromPoints(points);
- }
- }
- Shape$2.Polygon = Polygon;
- /**
- * @fileOverview convert the line to curve
- * @author dxq613@gmail.com
- */
- function getPoint(v) {
- return [v.x, v.y];
- }
- function smoothBezier(points, smooth, isLoop, constraint) {
- var cps = [];
- var prevPoint;
- var nextPoint;
- var hasConstraint = !!constraint;
- var min;
- var max;
- var point;
- var len;
- var l;
- var i;
- if (hasConstraint) {
- min = [Infinity, Infinity];
- max = [-Infinity, -Infinity];
- for (i = 0, l = points.length; i < l; i++) {
- point = getPoint(points[i]);
- Vector2.min(min, min, point);
- Vector2.max(max, max, point);
- }
- Vector2.min(min, min, constraint[0]);
- Vector2.max(max, max, constraint[1]);
- }
- for (i = 0, len = points.length; i < len; i++) {
- point = getPoint(points[i]);
- if (isLoop) {
- prevPoint = getPoint(points[i ? i - 1 : len - 1]);
- nextPoint = getPoint(points[(i + 1) % len]);
- } else {
- if (i === 0 || i === len - 1) {
- cps.push([point[0], point[1]]);
- continue;
- } else {
- prevPoint = getPoint(points[i - 1]);
- nextPoint = getPoint(points[i + 1]);
- }
- }
- var v = Vector2.sub([], nextPoint, prevPoint);
- Vector2.scale(v, v, smooth);
- var d0 = Vector2.distance(point, prevPoint);
- var d1 = Vector2.distance(point, nextPoint);
- var sum = d0 + d1;
- if (sum !== 0) {
- d0 /= sum;
- d1 /= sum;
- }
- var v1 = Vector2.scale([], v, -d0);
- var v2 = Vector2.scale([], v, d1);
- var cp0 = Vector2.add([], point, v1);
- var cp1 = Vector2.add([], point, v2);
- if (hasConstraint) {
- Vector2.max(cp0, cp0, min);
- Vector2.min(cp0, cp0, max);
- Vector2.max(cp1, cp1, min);
- Vector2.min(cp1, cp1, max);
- }
- cps.push([cp0[0], cp0[1]]);
- cps.push([cp1[0], cp1[1]]);
- }
- if (isLoop) {
- cps.push(cps.shift());
- }
- return cps;
- }
- function catmullRom2bezier(pointList, z, constraint) {
- var isLoop = !!z;
- var controlPointList = smoothBezier(pointList, 0.4, isLoop, constraint);
- var len = pointList.length;
- var d1 = [];
- var cp1;
- var cp2;
- var p;
- for (var i = 0; i < len - 1; i++) {
- cp1 = controlPointList[i * 2];
- cp2 = controlPointList[i * 2 + 1];
- p = pointList[i + 1];
- d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
- }
- if (isLoop) {
- cp1 = controlPointList[len];
- cp2 = controlPointList[len + 1];
- p = pointList[0];
- d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
- }
- return d1;
- }
- function _filterPoints(points) {
- var filteredPoints = [];
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- if (!isNaN(point.x) && !isNaN(point.y)) {
- filteredPoints.push(point);
- }
- }
- return filteredPoints;
- }
- class Polyline extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'polyline';
- }
- getDefaultAttrs() {
- return {
- points: null,
- lineWidth: 1,
- smooth: false
- };
- }
- createPath(context) {
- var self = this;
- var attrs = self.get('attrs');
- var {
- points,
- smooth
- } = attrs;
- var filteredPoints = _filterPoints(points);
- context.beginPath();
- if (filteredPoints.length) {
- context.moveTo(filteredPoints[0].x, filteredPoints[0].y);
- if (smooth) {
- var constaint = [[0, 0], [1, 1]];
- var sps = catmullRom2bezier(filteredPoints, false, constaint);
- for (var i = 0, n = sps.length; i < n; i++) {
- var sp = sps[i];
- context.bezierCurveTo(sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]);
- }
- } else {
- var _i;
- var l;
- for (_i = 1, l = filteredPoints.length - 1; _i < l; _i++) {
- context.lineTo(filteredPoints[_i].x, filteredPoints[_i].y);
- }
- context.lineTo(filteredPoints[l].x, filteredPoints[l].y);
- }
- }
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- points,
- smooth,
- lineWidth
- } = attrs;
- var filteredPoints = _filterPoints(points);
- if (smooth) {
- var newPoints = [];
- var constaint = [[0, 0], [1, 1]];
- var sps = catmullRom2bezier(filteredPoints, false, constaint);
- for (var i = 0, n = sps.length; i < n; i++) {
- var sp = sps[i];
- if (i === 0) {
- newPoints.push([filteredPoints[0].x, filteredPoints[0].y, sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
- } else {
- var lastPoint = sps[i - 1];
- newPoints.push([lastPoint[5], lastPoint[6], sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
- }
- }
- return getBBoxFromBezierGroup(newPoints, lineWidth);
- }
- return getBBoxFromPoints(filteredPoints, lineWidth);
- }
- }
- Shape$2.Polyline = Polyline;
- class Arc extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canStroke = true;
- this._attrs.canFill = true;
- this._attrs.type = 'arc';
- }
- getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- r: 0,
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false,
- lineWidth: 1
- };
- }
- createPath(context) {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- r,
- startAngle,
- endAngle,
- anticlockwise
- } = attrs;
- context.beginPath();
- if (startAngle !== endAngle) {
- context.arc(x, y, r, startAngle, endAngle, anticlockwise);
- }
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- r,
- startAngle,
- endAngle,
- anticlockwise
- } = attrs;
- return getBBoxFromArc(x, y, r, startAngle, endAngle, anticlockwise);
- }
- }
- Shape$2.Arc = Arc;
- class Sector extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'sector';
- }
- getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- lineWidth: 0,
- r: 0,
- r0: 0,
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- };
- }
- createPath(context) {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- startAngle,
- endAngle,
- r,
- r0,
- anticlockwise
- } = attrs;
- context.beginPath();
- var unitX = Math.cos(startAngle);
- var unitY = Math.sin(startAngle);
- context.moveTo(unitX * r0 + x, unitY * r0 + y);
- context.lineTo(unitX * r + x, unitY * r + y); // 当扇形的角度非常小的时候,就不进行弧线的绘制;或者整个只有1个扇形时,会出现end<0的情况不绘制
- if (Math.abs(endAngle - startAngle) > 0.0001 || startAngle === 0 && endAngle < 0) {
- context.arc(x, y, r, startAngle, endAngle, anticlockwise);
- context.lineTo(Math.cos(endAngle) * r0 + x, Math.sin(endAngle) * r0 + y);
- if (r0 !== 0) {
- context.arc(x, y, r0, endAngle, startAngle, !anticlockwise);
- }
- }
- context.closePath();
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- r,
- r0,
- startAngle,
- endAngle,
- anticlockwise
- } = attrs;
- var outerBBox = getBBoxFromArc(x, y, r, startAngle, endAngle, anticlockwise);
- var innerBBox = getBBoxFromArc(x, y, r0, startAngle, endAngle, anticlockwise);
- return {
- minX: Math.min(outerBBox.minX, innerBBox.minX),
- minY: Math.min(outerBBox.minY, innerBBox.minY),
- maxX: Math.max(outerBBox.maxX, innerBBox.maxX),
- maxY: Math.max(outerBBox.maxY, innerBBox.maxY)
- };
- }
- }
- Shape$2.Sector = Sector;
- var Rect$1 = {
- calcRotatedBox(_ref) {
- var {
- width,
- height,
- rotate
- } = _ref;
- var absRotate = Math.abs(rotate);
- return {
- width: Math.abs(width * Math.cos(absRotate) + height * Math.sin(absRotate)),
- height: Math.abs(height * Math.cos(absRotate) + width * Math.sin(absRotate))
- };
- }
- };
- var textWidthCacheCounter = 0;
- var textWidthCache = {};
- var TEXT_CACHE_MAX = 5000;
- class Text extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'text';
- }
- getDefaultAttrs() {
- return {
- lineWidth: 0,
- lineCount: 1,
- fontSize: 12,
- fontFamily: 'sans-serif',
- fontStyle: 'normal',
- fontWeight: 'normal',
- fontVariant: 'normal',
- textAlign: 'start',
- textBaseline: 'bottom',
- lineHeight: null,
- textArr: null
- };
- }
- _getFontStyle() {
- var attrs = this._attrs.attrs;
- var {
- fontSize,
- fontFamily,
- fontWeight,
- fontStyle,
- fontVariant
- } = attrs;
- return "".concat(fontStyle, " ").concat(fontVariant, " ").concat(fontWeight, " ").concat(fontSize, "px ").concat(fontFamily);
- }
- _afterAttrsSet() {
- var attrs = this._attrs.attrs;
- attrs.font = this._getFontStyle();
- if (attrs.text) {
- var text = attrs.text;
- var textArr = null;
- var lineCount = 1;
- if (isString(text) && text.indexOf('\n') !== -1) {
- textArr = text.split('\n');
- lineCount = textArr.length;
- }
- attrs.lineCount = lineCount;
- attrs.textArr = textArr;
- }
- this.set('attrs', attrs);
- }
- _getTextHeight() {
- var attrs = this._attrs.attrs;
- if (attrs.height) {
- return attrs.height;
- }
- var lineCount = attrs.lineCount;
- var fontSize = attrs.fontSize * 1;
- if (lineCount > 1) {
- var spaceingY = this._getSpaceingY();
- return fontSize * lineCount + spaceingY * (lineCount - 1);
- }
- return fontSize;
- }
- _getSpaceingY() {
- var attrs = this._attrs.attrs;
- var lineHeight = attrs.lineHeight;
- var fontSize = attrs.fontSize * 1;
- return lineHeight ? lineHeight - fontSize : fontSize * 0.14;
- }
- drawInner(context) {
- var self = this;
- var attrs = self._attrs.attrs;
- var text = attrs.text;
- var x = attrs.x;
- var y = attrs.y;
- if (isNil(text) || isNaN(x) || isNaN(y)) {
- // text will be 0
- return;
- }
- var textArr = attrs.textArr;
- var fontSize = attrs.fontSize * 1;
- var spaceingY = self._getSpaceingY();
- if (attrs.rotate) {
- // do rotation
- context.translate(x, y);
- context.rotate(attrs.rotate);
- x = 0;
- y = 0;
- }
- var textBaseline = attrs.textBaseline;
- var height;
- if (textArr) {
- height = self._getTextHeight();
- }
- var subY; // context.beginPath();
- if (self.hasFill()) {
- var fillOpacity = attrs.fillOpacity;
- if (!isNil(fillOpacity) && fillOpacity !== 1) {
- context.globalAlpha = fillOpacity;
- }
- if (textArr) {
- for (var i = 0, len = textArr.length; i < len; i++) {
- var subText = textArr[i];
- subY = y + i * (spaceingY + fontSize) - height + fontSize; // bottom;
- if (textBaseline === 'middle') {
- subY += height - fontSize - (height - fontSize) / 2;
- }
- if (textBaseline === 'top') {
- subY += height - fontSize;
- }
- context.fillText(subText, x, subY);
- }
- } else {
- context.fillText(text, x, y);
- }
- }
- if (self.hasStroke()) {
- if (textArr) {
- for (var _i = 0, _len = textArr.length; _i < _len; _i++) {
- var _subText = textArr[_i];
- subY = y + _i * (spaceingY + fontSize) - height + fontSize; // bottom;
- if (textBaseline === 'middle') {
- subY += height - fontSize - (height - fontSize) / 2;
- }
- if (textBaseline === 'top') {
- subY += height - fontSize;
- }
- context.strokeText(_subText, x, subY);
- }
- } else {
- context.strokeText(text, x, y);
- }
- }
- }
- calculateBox() {
- var self = this;
- var attrs = self._attrs.attrs;
- var {
- x,
- y,
- textAlign,
- textBaseline
- } = attrs;
- var width = self._getTextWidth(); // attrs.width
- if (!width) {
- return {
- minX: x,
- minY: y,
- maxX: x,
- maxY: y
- };
- }
- var height = self._getTextHeight(); // attrs.height
- if (attrs.rotate) {
- var rotatedBox = Rect$1.calcRotatedBox({
- width,
- height,
- rotate: attrs.rotate
- });
- width = rotatedBox.width;
- height = rotatedBox.height;
- }
- var point = {
- x,
- y: y - height
- }; // default textAlign: start, textBaseline: bottom
- if (textAlign) {
- if (textAlign === 'end' || textAlign === 'right') {
- point.x -= width;
- } else if (textAlign === 'center') {
- point.x -= width / 2;
- }
- }
- if (textBaseline) {
- if (textBaseline === 'top') {
- point.y += height;
- } else if (textBaseline === 'middle') {
- point.y += height / 2;
- }
- }
- return {
- minX: point.x,
- minY: point.y,
- maxX: point.x + width,
- maxY: point.y + height
- };
- }
- _getTextWidth() {
- var attrs = this._attrs.attrs;
- if (attrs.width) {
- return attrs.width;
- }
- var text = attrs.text;
- var context = this.get('context');
- if (isNil(text)) return undefined;
- var font = attrs.font;
- var textArr = attrs.textArr;
- var key = text + '' + font;
- if (textWidthCache[key]) {
- return textWidthCache[key];
- }
- var width = 0;
- if (textArr) {
- for (var i = 0, length = textArr.length; i < length; i++) {
- var subText = textArr[i];
- width = Math.max(width, measureText(subText, font, context).width);
- }
- } else {
- width = measureText(text, font, context).width;
- }
- if (textWidthCacheCounter > TEXT_CACHE_MAX) {
- textWidthCacheCounter = 0;
- textWidthCache = {};
- }
- textWidthCacheCounter++;
- textWidthCache[key] = width;
- return width;
- }
- }
- Shape$2.Text = Text;
- class Custom extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.createPath = null;
- this._attrs.type = 'custom';
- }
- createPath(context) {
- var createPath = this.get('createPath');
- createPath && createPath.call(this, context);
- }
- calculateBox() {
- var calculateBox = this.get('calculateBox');
- return calculateBox && calculateBox.call(this);
- }
- }
- Shape$2.Custom = Custom;
- var G = /*#__PURE__*/Object.freeze({
- __proto__: null,
- Canvas: Canvas,
- Group: Group,
- Shape: Shape$2,
- Matrix: Matrix,
- Vector2: Vector2
- });
- function formatTicks(ticks) {
- var tmp = ticks.slice(0);
- if (tmp.length > 0) {
- var first = tmp[0];
- var last = tmp[tmp.length - 1];
- if (first.value !== 0) {
- tmp.unshift({
- value: 0
- });
- }
- if (last.value !== 1) {
- tmp.push({
- value: 1
- });
- }
- }
- return tmp;
- }
- class AxisController {
- constructor(cfg) {
- this.axisCfg = {};
- this.frontPlot = null;
- this.backPlot = null;
- this.axes = {}; // store the axes's options
- mix(this, cfg);
- }
- _isHide(field) {
- var axisCfg = this.axisCfg;
- return !axisCfg || axisCfg[field] === false;
- }
- _getLinePosition(scale, dimType, index, transposed) {
- var position = '';
- var field = scale.field;
- var axisCfg = this.axisCfg;
- if (axisCfg[field] && axisCfg[field].position) {
- position = axisCfg[field].position;
- } else if (dimType === 'x') {
- position = transposed ? 'left' : 'bottom';
- } else if (dimType === 'y') {
- position = index ? 'right' : 'left';
- if (transposed) {
- position = 'bottom';
- }
- }
- return position;
- }
- _getLineCfg(coord, dimType, position) {
- var start;
- var end;
- var factor = 1; // Mark clockwise or counterclockwise
- if (dimType === 'x') {
- start = {
- x: 0,
- y: 0
- };
- end = {
- x: 1,
- y: 0
- };
- } else {
- if (position === 'right') {
- // there will be several y axes
- start = {
- x: 1,
- y: 0
- };
- end = {
- x: 1,
- y: 1
- };
- } else {
- start = {
- x: 0,
- y: 0
- };
- end = {
- x: 0,
- y: 1
- };
- factor = -1;
- }
- }
- if (coord.transposed) {
- factor *= -1;
- }
- return {
- offsetFactor: factor,
- start: coord.convertPoint(start),
- end: coord.convertPoint(end)
- };
- }
- _getCircleCfg(coord) {
- return {
- startAngle: coord.startAngle,
- endAngle: coord.endAngle,
- center: coord.center,
- radius: coord.circleRadius
- };
- }
- _getRadiusCfg(coord) {
- var transposed = coord.transposed;
- var start;
- var end;
- if (transposed) {
- start = {
- x: 0,
- y: 0
- };
- end = {
- x: 1,
- y: 0
- };
- } else {
- start = {
- x: 0,
- y: 0
- };
- end = {
- x: 0,
- y: 1
- };
- }
- return {
- offsetFactor: -1,
- start: coord.convertPoint(start),
- end: coord.convertPoint(end)
- };
- }
- _getAxisCfg(coord, scale, verticalScale, dimType, defaultCfg) {
- var self = this;
- var axisCfg = this.axisCfg;
- var ticks = scale.getTicks();
- var cfg = deepMix({
- ticks,
- frontContainer: this.frontPlot,
- backContainer: this.backPlot
- }, defaultCfg, axisCfg[scale.field]);
- var labels = [];
- var label = cfg.label;
- var count = ticks.length;
- var maxWidth = 0;
- var maxHeight = 0;
- var labelCfg = label;
- each(ticks, function (tick, index) {
- if (isFunction(label)) {
- var executedLabel = label(tick.text, index, count);
- labelCfg = executedLabel ? mix({}, Global._defaultAxis.label, executedLabel) : null;
- }
- if (labelCfg) {
- var textStyle = {};
- if (labelCfg.textAlign) {
- textStyle.textAlign = labelCfg.textAlign;
- }
- if (labelCfg.textBaseline) {
- textStyle.textBaseline = labelCfg.textBaseline;
- }
- var axisLabel = new Shape$2.Text({
- className: 'axis-label',
- attrs: mix({
- x: 0,
- y: 0,
- text: tick.text,
- fontFamily: self.chart.get('canvas').get('fontFamily')
- }, labelCfg),
- value: tick.value,
- textStyle,
- top: labelCfg.top,
- context: self.chart.get('canvas').get('context')
- });
- labels.push(axisLabel);
- var {
- width,
- height
- } = axisLabel.getBBox();
- maxWidth = Math.max(maxWidth, width);
- maxHeight = Math.max(maxHeight, height);
- }
- });
- cfg.labels = labels;
- cfg.maxWidth = maxWidth;
- cfg.maxHeight = maxHeight;
- return cfg;
- }
- _createAxis(coord, scale, verticalScale, dimType) {
- var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
- var self = this;
- var coordType = coord.type;
- var transposed = coord.transposed;
- var type;
- var key;
- var defaultCfg;
- if (coordType === 'cartesian' || coordType === 'rect') {
- var position = self._getLinePosition(scale, dimType, index, transposed);
- defaultCfg = Global.axis[position];
- defaultCfg.position = position;
- type = 'Line';
- key = position;
- } else {
- if (dimType === 'x' && !transposed || dimType === 'y' && transposed) {
- defaultCfg = Global.axis.circle;
- type = 'Circle';
- key = 'circle';
- } else {
- defaultCfg = Global.axis.radius;
- type = 'Line';
- key = 'radius';
- }
- }
- var cfg = self._getAxisCfg(coord, scale, verticalScale, dimType, defaultCfg);
- cfg.type = type;
- cfg.dimType = dimType;
- cfg.verticalScale = verticalScale;
- cfg.index = index;
- this.axes[key] = cfg;
- }
- createAxis(coord, xScale, yScales) {
- var self = this;
- if (xScale && !self._isHide(xScale.field)) {
- self._createAxis(coord, xScale, yScales[0], 'x');
- }
- each(yScales, function (yScale, index) {
- if (!self._isHide(yScale.field)) {
- self._createAxis(coord, yScale, xScale, 'y', index);
- }
- });
- var axes = this.axes;
- var chart = self.chart;
- if (chart._isAutoPadding()) {
- var userPadding = parsePadding(chart.get('padding'));
- var appendPadding = parsePadding(chart.get('appendPadding'));
- var legendRange = chart.get('legendRange') || {
- top: 0,
- right: 0,
- bottom: 0,
- left: 0
- };
- var padding = [userPadding[0] === 'auto' ? legendRange.top + appendPadding[0] * 2 : userPadding[0], userPadding[1] === 'auto' ? legendRange.right + appendPadding[1] : userPadding[1], userPadding[2] === 'auto' ? legendRange.bottom + appendPadding[2] : userPadding[2], userPadding[3] === 'auto' ? legendRange.left + appendPadding[3] : userPadding[3]];
- if (coord.isPolar) {
- var circleAxis = axes.circle;
- if (circleAxis) {
- var {
- maxHeight,
- maxWidth,
- labelOffset
- } = circleAxis;
- padding[0] += maxHeight + labelOffset;
- padding[1] += maxWidth + labelOffset;
- padding[2] += maxHeight + labelOffset;
- padding[3] += maxWidth + labelOffset;
- }
- } else {
- if (axes.right && userPadding[1] === 'auto') {
- var {
- maxWidth: _maxWidth,
- labelOffset: _labelOffset
- } = axes.right;
- padding[1] += _maxWidth + _labelOffset;
- }
- if (axes.left && userPadding[3] === 'auto') {
- var {
- maxWidth: _maxWidth2,
- labelOffset: _labelOffset2
- } = axes.left;
- padding[3] += _maxWidth2 + _labelOffset2;
- }
- if (axes.bottom && userPadding[2] === 'auto') {
- var {
- maxHeight: _maxHeight,
- labelOffset: _labelOffset3
- } = axes.bottom;
- padding[2] += _maxHeight + _labelOffset3;
- }
- }
- chart.set('_padding', padding);
- chart._updateLayout(padding);
- }
- each(axes, function (axis) {
- var {
- type,
- grid,
- verticalScale,
- ticks,
- dimType,
- position,
- index
- } = axis;
- var appendCfg;
- if (coord.isPolar) {
- if (type === 'Line') {
- appendCfg = self._getRadiusCfg(coord);
- } else if (type === 'Circle') {
- appendCfg = self._getCircleCfg(coord);
- }
- } else {
- appendCfg = self._getLineCfg(coord, dimType, position);
- }
- if (grid && verticalScale) {
- var gridPoints = [];
- var verticalTicks = formatTicks(verticalScale.getTicks());
- each(ticks, function (tick) {
- var subPoints = [];
- each(verticalTicks, function (verticalTick) {
- var x = dimType === 'x' ? tick.value : verticalTick.value;
- var y = dimType === 'x' ? verticalTick.value : tick.value;
- if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
- var point = coord.convertPoint({
- x,
- y
- });
- subPoints.push(point);
- }
- });
- gridPoints.push({
- points: subPoints,
- _id: 'axis-' + dimType + index + '-grid-' + tick.tickValue
- });
- });
- axis.gridPoints = gridPoints;
- if (coord.isPolar) {
- axis.center = coord.center;
- axis.startAngle = coord.startAngle;
- axis.endAngle = coord.endAngle;
- }
- }
- appendCfg._id = 'axis-' + dimType;
- if (!isNil(index)) {
- appendCfg._id = 'axis-' + dimType + index;
- }
- new Abastract[type](mix(axis, appendCfg));
- });
- }
- clear() {
- this.axes = {};
- this.frontPlot.clear();
- this.backPlot.clear();
- }
- }
- function getClip(coord) {
- var start = coord.start;
- var end = coord.end;
- var width = end.x - start.x;
- var height = Math.abs(end.y - start.y);
- var margin = 10;
- var clip;
- if (coord.isPolar) {
- var {
- circleRadius,
- center,
- startAngle,
- endAngle
- } = coord;
- clip = new Shape$2.Sector({
- attrs: {
- x: center.x,
- y: center.y,
- r: circleRadius,
- r0: 0,
- startAngle,
- endAngle
- }
- });
- } else {
- clip = new Shape$2.Rect({
- attrs: {
- x: start.x,
- y: end.y - margin,
- width,
- height: height + 2 * margin
- }
- });
- }
- clip.isClip = true;
- return clip;
- }
- function isPointInPlot(point, plot) {
- var {
- x,
- y
- } = point;
- var {
- tl,
- tr,
- br
- } = plot;
- return x >= tl.x && x <= tr.x && y >= tl.y && y <= br.y;
- }
- var Helper = /*#__PURE__*/Object.freeze({
- __proto__: null,
- getClip: getClip,
- isPointInPlot: isPointInPlot
- });
- function compare(a, b) {
- return a - b;
- }
- function _isScaleExist(scales, compareScale) {
- var flag = false;
- each(scales, function (scale) {
- var scaleValues = [].concat(scale.values);
- var compareScaleValues = [].concat(compareScale.values);
- if (scale.type === compareScale.type && scale.field === compareScale.field && scaleValues.sort(compare).toString() === compareScaleValues.sort(compare).toString()) {
- flag = true;
- return;
- }
- });
- return flag;
- }
- class Chart extends Base {
- static initPlugins() {
- return {
- _plugins: [],
- _cacheId: 0,
- register(plugins) {
- var p = this._plugins;
- [].concat(plugins).forEach(function (plugin) {
- if (p.indexOf(plugin) === -1) {
- p.push(plugin);
- }
- });
- this._cacheId++;
- },
- unregister(plugins) {
- var p = this._plugins;
- [].concat(plugins).forEach(function (plugin) {
- var idx = p.indexOf(plugin);
- if (idx !== -1) {
- p.splice(idx, 1);
- }
- });
- this._cacheId++;
- },
- clear() {
- this._plugins = [];
- this._cacheId++;
- },
- count() {
- return this._plugins.length;
- },
- getAll() {
- return this._plugins;
- },
- notify(chart, hook, args) {
- var descriptors = this.descriptors(chart);
- var ilen = descriptors.length;
- var i;
- var descriptor;
- var plugin;
- var params;
- var method;
- for (i = 0; i < ilen; ++i) {
- descriptor = descriptors[i];
- plugin = descriptor.plugin;
- method = plugin[hook];
- if (typeof method === 'function') {
- params = [chart].concat(args || []);
- if (method.apply(plugin, params) === false) {
- return false;
- }
- }
- }
- return true;
- },
- descriptors(chart) {
- var cache = chart._plugins || (chart._plugins = {});
- if (cache.id === this._cacheId) {
- return cache.descriptors;
- }
- var plugins = [];
- var descriptors = [];
- this._plugins.concat(chart && chart.get('plugins') || []).forEach(function (plugin) {
- var idx = plugins.indexOf(plugin);
- if (idx !== -1) {
- return;
- }
- plugins.push(plugin);
- descriptors.push({
- plugin
- });
- });
- cache.descriptors = descriptors;
- cache.id = this._cacheId;
- return descriptors;
- }
- };
- }
- getDefaultCfg() {
- return {
- /**
- * the id of canvas
- * @type {String}
- */
- id: null,
- rendered: false,
- /**
- * padding
- * @type {Array|Number}
- */
- padding: Global.padding,
- /**
- * data
- * @type {Array}
- */
- data: null,
- /**
- * scales of chart
- * @type {Object}
- */
- scales: {},
- /**
- * @private
- * geometry instances
- * @type {Array}
- */
- geoms: [],
- /**
- * scale configuration
- * @type {Object}
- */
- colDefs: null,
- pixelRatio: Global.pixelRatio,
- /**
- * filter options
- * @type {Object}
- */
- filters: null,
- appendPadding: Global.appendPadding
- };
- }
- _syncYScales() {
- var syncY = this.get('syncY');
- if (!syncY) {
- return;
- }
- var geoms = this.get('geoms');
- var syncScales = [];
- var min = [];
- var max = [];
- each(geoms, function (geom) {
- var yScale = geom.getYScale();
- if (yScale.isLinear) {
- syncScales.push(yScale);
- min.push(yScale.min);
- max.push(yScale.max);
- }
- });
- min = Math.min.apply(null, min);
- max = Math.max.apply(null, max);
- each(syncScales, function (scale) {
- scale.change({
- min
- });
- scale.change({
- max
- });
- });
- }
- _getFieldsForLegend() {
- var fields = [];
- var geoms = this.get('geoms');
- each(geoms, function (geom) {
- var attrOptions = geom.get('attrOptions');
- var attrCfg = attrOptions.color;
- if (attrCfg && attrCfg.field && isString(attrCfg.field)) {
- var arr = attrCfg.field.split('*');
- each(arr, function (item) {
- if (fields.indexOf(item) === -1) {
- fields.push(item);
- }
- });
- }
- });
- return fields;
- }
- _getScaleData(field) {
- var data = this.get('data');
- var filteredData = this.get('filteredData');
- if (filteredData.length) {
- var legendFields = this._getFieldsForLegend();
- if (legendFields.indexOf(field) === -1) {
- data = filteredData;
- }
- }
- return data;
- } // _updateScales() {
- // const scaleController = this.get('scaleController');
- // scaleController.updateScales();
- // this._adjustScale();
- // }
- _adjustScale() {
- var self = this;
- var scaleController = self.get('scaleController'); // 看起来是为了让柱状图最小或最大都默认从0开始
- var geoms = this.get('geoms');
- for (var i = 0; i < geoms.length; i++) {
- var geom = geoms[i];
- if (geom.get('type') === 'interval') {
- var yScale = geom.getYScale();
- scaleController.adjustStartZero(yScale);
- }
- }
- }
- _removeGeoms() {
- var geoms = this.get('geoms');
- while (geoms.length > 0) {
- var geom = geoms.shift();
- geom.destroy();
- }
- }
- _clearGeoms() {
- var geoms = this.get('geoms');
- for (var i = 0, length = geoms.length; i < length; i++) {
- var geom = geoms[i];
- geom.clear();
- }
- }
- _clearInner() {
- this._clearGeoms();
- Chart.plugins.notify(this, 'clearInner');
- this.emit(EVENT_CLEAR_INNER);
- this.get('axisController') && this.get('axisController').clear();
- }
- _initFilteredData() {
- var filters = this.get('filters');
- var data = this.get('data') || [];
- if (filters) {
- data = data.filter(function (obj) {
- var rst = true;
- each(filters, function (fn, k) {
- if (fn) {
- rst = fn(obj[k], obj);
- if (!rst) {
- return false;
- }
- }
- });
- return rst;
- });
- }
- this.set('filteredData', data);
- }
- _changeGeomsData() {
- var geoms = this.get('geoms');
- var data = this.get('filteredData');
- for (var i = 0, length = geoms.length; i < length; i++) {
- var geom = geoms[i];
- geom.changeData(data);
- }
- }
- _initGeom(geom) {
- if (geom.get('isInit')) {
- return;
- }
- var coord = this.get('coord');
- var data = this.get('filteredData');
- var colDefs = this.get('colDefs');
- var middlePlot = this.get('middlePlot');
- geom.set('chart', this);
- geom.set('container', middlePlot.addGroup());
- geom.set('data', data);
- geom.set('coord', coord);
- geom.set('colDefs', colDefs);
- geom.init();
- this.emit(EVENT_AFTER_GEOM_INIT, geom);
- }
- _initGeoms() {
- var geoms = this.get('geoms');
- for (var i = 0, length = geoms.length; i < length; i++) {
- this._initGeom(geoms[i]);
- }
- }
- _initCoord() {
- var plot = this.get('plotRange');
- var coordCfg = mix({
- type: 'cartesian'
- }, this.get('coordCfg'), {
- plot
- });
- var type = coordCfg.type;
- var C = Base$1[upperFirst(type)];
- var coord = new C(coordCfg);
- this.set('coord', coord);
- }
- _initLayout() {
- var padding = this.get('_padding');
- if (!padding) {
- padding = this.get('margin') || this.get('padding');
- padding = parsePadding(padding);
- }
- var top = padding[0] === 'auto' ? 0 : padding[0];
- var right = padding[1] === 'auto' ? 0 : padding[1];
- var bottom = padding[2] === 'auto' ? 0 : padding[2];
- var left = padding[3] === 'auto' ? 0 : padding[3];
- var width = this.get('width');
- var height = this.get('height');
- var start = {
- x: left,
- y: top
- };
- var end = {
- x: width - right,
- y: height - bottom
- };
- var plot = this.get('plot');
- if (plot) {
- plot.reset(start, end);
- return;
- }
- var newPlot = new Plot({
- start,
- end
- });
- this.set('plotRange', newPlot);
- this.set('plot', newPlot);
- }
- _initCanvas() {
- var self = this;
- try {
- var canvas = new Canvas({
- el: self.get('el') || self.get('id'),
- context: self.get('context'),
- pixelRatio: self.get('pixelRatio'),
- width: self.get('width'),
- height: self.get('height'),
- fontFamily: Global.fontFamily
- });
- self.set('canvas', canvas);
- self.set('el', canvas.get('el'));
- self.set('width', canvas.get('width'));
- self.set('height', canvas.get('height'));
- } catch (error) {
- throw error;
- }
- Chart.plugins.notify(self, 'afterCanvasInit');
- }
- _initLayers() {
- var canvas = this.get('canvas');
- this.set('backPlot', canvas.addGroup());
- this.set('middlePlot', canvas.addGroup({
- zIndex: 10
- }));
- this.set('frontPlot', canvas.addGroup({
- zIndex: 20
- }));
- }
- _initEvents() {
- var _this = this;
- // 数据更新后的一些更新
- this.on(EVENT_AFTER_DATA_CHANGE, function () {
- // 数据更新后,重新设置filterdata
- _this._initFilteredData(); // 更新geoms里的数据
- _this._changeGeomsData();
- }); // 大小变化后的一些更新
- this.on(EVENT_AFTER_SIZE_CHANGE, function () {
- _this._initLayout(); // layout变化后,坐标轴也需要做相应的变化
- var coord = _this.get('coord');
- if (coord) {
- coord.reset(_this.get('plot'));
- }
- });
- }
- _initScaleController() {
- var scaleController = new ScaleController({
- chart: this
- }); // 让colDefs 和 scaleController.defs 用同一个对象,这样就不用考虑同步的问题
- this.set('colDefs', scaleController.defs); // 已经实例化的scales 也保持统一个对象
- this.set('scales', scaleController.scales);
- this.set('scaleController', scaleController);
- }
- _clearScaleController() {
- var scaleController = this.get('scaleController');
- scaleController.clear();
- }
- _init() {
- var self = this;
- self._initCanvas();
- self._initLayout();
- self._initLayers();
- self._initEvents();
- self._initScaleController();
- self.set('axisController', new AxisController({
- frontPlot: self.get('frontPlot').addGroup({
- className: 'axisContainer'
- }),
- backPlot: self.get('backPlot').addGroup({
- className: 'axisContainer'
- }),
- chart: self
- }));
- Chart.plugins.notify(self, 'init');
- }
- constructor(cfg) {
- super(cfg);
- var self = this;
- each(Geom, function (geomConstructor, className) {
- var methodName = lowerFirst(className);
- self[methodName] = function (cfg) {
- var geom = new geomConstructor(cfg);
- self.addGeom(geom);
- return geom;
- };
- });
- self._init();
- }
- init() {
- // 初始filterData
- this._initFilteredData(); // initialization coordinate instance
- this._initCoord();
- Chart.plugins.notify(this, 'beforeGeomInit'); // init all geometry instances
- this._initGeoms(); // 多 Y 轴的情况时,统一 Y 轴的数值范围。
- this._syncYScales(); // do some adjust for data
- this._adjustScale();
- this.emit(EVENT_AFTER_INIT);
- }
- /**
- * set data and some scale configuration
- * @chainable
- * @param {Array} data the dataset to visualize
- * @param {Object} colDefs the configuration for scales
- * @return {Chart} return the chart instance
- */
- source(data, colDefs) {
- this.set('data', data);
- if (colDefs) {
- this.scale(colDefs);
- }
- return this;
- }
- scale(field, cfg) {
- var scaleController = this.get('scaleController');
- scaleController.setFieldDef(field, cfg);
- return this;
- }
- /**
- * configure the axis
- * @chainable
- * @param {String|Boolean} field the field name of data
- * @param {Object} cfg configuration for axis
- * @return {Chart} return the chart instance
- */
- axis(field, cfg) {
- var axisController = this.get('axisController');
- if (!field) {
- axisController.axisCfg = null;
- } else {
- axisController.axisCfg = axisController.axisCfg || {};
- axisController.axisCfg[field] = cfg;
- }
- return this;
- }
- /**
- * configure the coordinate
- * @chainable
- * @param {String} type set the type of coodinate
- * @param {Object} cfg configuration for coordinate
- * @return {Chart} return the chart instance
- */
- coord(type, cfg) {
- var coordCfg;
- if (isObject(type)) {
- coordCfg = type;
- } else {
- coordCfg = cfg || {};
- coordCfg.type = type || 'cartesian';
- }
- this.set('coordCfg', coordCfg);
- return this;
- }
- filter(field, condition) {
- var filters = this.get('filters') || {};
- filters[field] = condition;
- this.set('filters', filters); // 如果已经render过,则再重新触发一次change
- if (this.get('rendered')) {
- this.emit(EVENT_AFTER_DATA_CHANGE, this.get('data'));
- }
- }
- /**
- * render the chart
- * @chainable
- * @return {Chart} return the chart instance
- */
- render() {
- var rendered = this.get('rendered');
- var canvas = this.get('canvas');
- var geoms = this.get('geoms'); // 已经渲染过
- if (rendered) {
- this._initGeoms();
- this._adjustScale();
- } else {
- this.init();
- this.set('rendered', true);
- }
- this.emit(EVENT_BEFORE_RENDER);
- Chart.plugins.notify(this, 'beforeGeomDraw');
- this._renderAxis();
- var middlePlot = this.get('middlePlot');
- if (this.get('limitInPlot') && !middlePlot.attr('clip')) {
- var coord = this.get('coord');
- var clip = getClip(coord);
- clip.set('canvas', middlePlot.get('canvas'));
- middlePlot.attr('clip', clip);
- }
- this.emit(EVENT_BEFORE_GEOM_DRAW);
- for (var i = 0, length = geoms.length; i < length; i++) {
- var geom = geoms[i];
- geom.paint();
- }
- this.emit(EVENT_AFTER_GEOM_DRAW);
- Chart.plugins.notify(this, 'afterGeomDraw');
- canvas.sort();
- this.get('frontPlot').sort();
- Chart.plugins.notify(this, 'beforeCanvasDraw');
- canvas.draw();
- this.emit(EVENT_AFTER_RENDER);
- return this;
- }
- /**
- * clear the chart, include geometris and all the shapes
- * @chainable
- * @return {Chart} return the chart
- */
- clear() {
- Chart.plugins.notify(this, 'clear');
- this.emit(EVENT_CLEAR);
- this._clearInner();
- this._removeGeoms();
- this._clearScaleController();
- this.set('legendItems', null);
- this.set('filters', null);
- this.set('isUpdate', false);
- this.set('_padding', null);
- this.set('rendered', false);
- var canvas = this.get('canvas');
- canvas.draw();
- return this;
- }
- repaint() {
- // 如果在没有render之前就repaint的,就直接return退出
- var rendered = this.get('rendered');
- if (!rendered) {
- return;
- }
- this.set('isUpdate', true);
- this.set('legendItems', null);
- Chart.plugins.notify(this, 'repaint');
- this._clearInner();
- this.emit(EVENT_REPAINT);
- this.render();
- }
- changeData(data) {
- this.emit(EVENT_BEFORE_DATA_CHANGE, data);
- this.set('data', data);
- Chart.plugins.notify(this, 'changeData');
- this.emit(EVENT_AFTER_DATA_CHANGE, data);
- this.set('_padding', null);
- this.repaint();
- }
- changeSize(width, height) {
- if (width) {
- this.set('width', width);
- } else {
- width = this.get('width');
- }
- if (height) {
- this.set('height', height);
- } else {
- height = this.get('height');
- }
- var canvas = this.get('canvas');
- canvas.changeSize(width, height);
- this.emit(EVENT_AFTER_SIZE_CHANGE, {
- width,
- height
- });
- this.repaint();
- return this;
- }
- destroy() {
- this.clear();
- var canvas = this.get('canvas');
- canvas.destroy();
- Chart.plugins.notify(this, 'afterCanvasDestroyed');
- if (this._interactions) {
- each(this._interactions, function (interaction) {
- interaction.destroy();
- });
- }
- super.destroy();
- }
- /**
- * calculate dataset's position on canvas
- * @param {Object} record the dataset
- * @return {Object} return the position
- */
- getPosition(record) {
- var self = this;
- var coord = self.get('coord');
- var xScale = self.getXScale();
- var xField = xScale.field;
- var yScales = self.getYScales(); // default first
- var yScale = yScales[0];
- var yField = yScale.field;
- for (var i = 0, len = yScales.length; i < len; i++) {
- var scale = yScales[i];
- var field = scale.field;
- if (record[field]) {
- yScale = scale;
- yField = field;
- break;
- }
- }
- var x = xScale.scale(record[xField]);
- var y = yScale.scale(record[yField]);
- return coord.convertPoint({
- x,
- y
- });
- }
- /**
- * get the data item of the point
- * @param {Object} point canvas position
- * @return {Object} return the data item
- */
- getRecord(point) {
- var self = this;
- var coord = self.get('coord');
- var xScale = self.getXScale();
- var yScale = self.getYScales()[0];
- var invertPoint = coord.invertPoint(point);
- var record = {};
- record[xScale.field] = xScale.invert(invertPoint.x);
- record[yScale.field] = yScale.invert(invertPoint.y);
- return record;
- }
- /**
- * get the dataset of the point
- * @param {Object} point canvas position
- * @return {Array} return the dataset
- **/
- getSnapRecords(point) {
- var geom = this.get('geoms')[0];
- var data = [];
- if (geom) {
- // need to judge
- data = geom.getSnapRecords(point);
- }
- return data;
- }
- /**
- * creat scale instances
- * @param {String} field field name of data
- * @return {Scale} return the scale
- */
- createScale(field) {
- var data = this._getScaleData(field);
- var scaleController = this.get('scaleController');
- return scaleController.createScale(field, data);
- }
- /**
- * @protected
- * add geometry instance to geoms
- * @param {Geom} geom geometry instance
- */
- addGeom(geom) {
- var geoms = this.get('geoms');
- geoms.push(geom);
- }
- /**
- * get the scale of x axis
- * @return {Scale} return the scale
- */
- getXScale() {
- var self = this;
- var geoms = self.get('geoms');
- var xScale = geoms[0].getXScale();
- return xScale;
- }
- /**
- * get the scale of y axis
- * @return {Array} return the scale
- */
- getYScales() {
- var geoms = this.get('geoms');
- var rst = [];
- each(geoms, function (geom) {
- var yScale = geom.getYScale();
- if (rst.indexOf(yScale) === -1) {
- rst.push(yScale);
- }
- });
- return rst;
- }
- getLegendItems() {
- if (this.get('legendItems')) {
- return this.get('legendItems');
- }
- var legendItems = {};
- var scales = [];
- var geoms = this.get('geoms');
- each(geoms, function (geom) {
- var colorAttr = geom.getAttr('color');
- if (colorAttr) {
- var scale = colorAttr.getScale('color'); // 只支持分类图例
- if (scale.isCategory && !_isScaleExist(scales, scale)) {
- scales.push(scale);
- var field = scale.field;
- var ticks = scale.getTicks();
- var items = [];
- each(ticks, function (tick) {
- var text = tick.text;
- var name = text;
- var scaleValue = tick.value;
- var value = scale.invert(scaleValue);
- var color = colorAttr.mapping(value).join('') || Global.defaultColor;
- var marker = {
- fill: color,
- radius: 3,
- symbol: 'circle',
- stroke: '#fff'
- };
- items.push({
- name,
- // for display
- dataValue: value,
- // the origin value
- checked: true,
- marker
- });
- });
- legendItems[field] = items;
- }
- }
- });
- this.set('legendItems', legendItems);
- return legendItems;
- } // register the plugins
- registerPlugins(plugins) {
- var self = this;
- var chartPlugins = self.get('plugins') || [];
- if (!isArray(chartPlugins)) {
- chartPlugins = [chartPlugins];
- }
- [].concat(plugins).forEach(function (plugin) {
- if (chartPlugins.indexOf(plugin) === -1) {
- plugin.init && plugin.init(self); // init
- chartPlugins.push(plugin);
- }
- });
- Chart.plugins._cacheId++;
- self.set('plugins', chartPlugins);
- }
- _renderAxis() {
- var axisController = this.get('axisController');
- var xScale = this.getXScale();
- var yScales = this.getYScales();
- var coord = this.get('coord');
- Chart.plugins.notify(this, 'beforeRenderAxis');
- axisController.createAxis(coord, xScale, yScales);
- }
- _isAutoPadding() {
- if (this.get('_padding')) {
- return false;
- }
- var padding = this.get('padding');
- if (isArray(padding)) {
- return padding.indexOf('auto') !== -1;
- }
- return padding === 'auto';
- }
- _updateLayout(padding) {
- var width = this.get('width');
- var height = this.get('height');
- var start = {
- x: padding[3],
- y: padding[0]
- };
- var end = {
- x: width - padding[1],
- y: height - padding[2]
- };
- var plot = this.get('plot');
- var coord = this.get('coord');
- plot.reset(start, end);
- coord.reset(plot);
- }
- }
- Chart.plugins = Chart.initPlugins();
- var track = function track() {
- return null;
- };
- /**
- * @fileOverview shape util
- * @author dxq613@gmail.com
- */
- function splitPoints(obj) {
- var points = [];
- var x = obj.x;
- var y = obj.y;
- y = isArray(y) ? y : [y];
- y.forEach(function (yItem, index) {
- var point = {
- x: isArray(x) ? x[index] : x,
- y: yItem
- };
- points.push(point);
- });
- return points;
- }
- function splitArray(data, yField, connectNulls) {
- if (!data.length) return [];
- var arr = [];
- var tmp = [];
- var yValue;
- each(data, function (obj) {
- yValue = obj._origin ? obj._origin[yField] : obj[yField];
- if (connectNulls) {
- if (!isNil(yValue)) {
- tmp.push(obj);
- }
- } else {
- if (isArray(yValue) && isNil(yValue[0]) || isNil(yValue)) {
- if (tmp.length) {
- arr.push(tmp);
- tmp = [];
- }
- } else {
- tmp.push(obj);
- }
- }
- });
- if (tmp.length) {
- arr.push(tmp);
- }
- return arr;
- }
- var SHAPES = ['circle', 'hollowCircle', 'rect'];
- var Point = Shape$1.registerFactory('point', {
- defaultShapeType: 'circle',
- getDefaultPoints(pointInfo) {
- return splitPoints(pointInfo);
- }
- });
- function getPointsCfg(cfg) {
- var style = {
- lineWidth: 0,
- stroke: cfg.color,
- fill: cfg.color
- };
- if (cfg.size) {
- style.size = cfg.size;
- }
- mix(style, cfg.style);
- return mix({}, Global.shape.point, style);
- }
- function drawShape(cfg, container, shape) {
- if (cfg.size === 0) return;
- var pointCfg = getPointsCfg(cfg);
- var size = pointCfg.r || pointCfg.size;
- var x = cfg.x;
- var y = !isArray(cfg.y) ? [cfg.y] : cfg.y;
- if (shape === 'hollowCircle') {
- pointCfg.lineWidth = 1;
- pointCfg.fill = null;
- }
- for (var i = 0, len = y.length; i < len; i++) {
- if (shape === 'rect') {
- return container.addShape('Rect', {
- className: 'point',
- attrs: mix({
- x: x - size,
- y: y[i] - size,
- width: size * 2,
- height: size * 2
- }, pointCfg)
- });
- }
- return container.addShape('Circle', {
- className: 'point',
- attrs: mix({
- x,
- y: y[i],
- r: size
- }, pointCfg)
- });
- }
- }
- each(SHAPES, function (shapeType) {
- Shape$1.registerShape('point', shapeType, {
- draw(cfg, container) {
- return drawShape(cfg, container, shapeType);
- }
- });
- });
- class Point$1 extends Geom {
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'point';
- cfg.shapeType = 'point';
- cfg.generatePoints = false;
- return cfg;
- }
- draw(data, shapeFactory) {
- var self = this;
- var container = self.get('container');
- each(data, function (obj) {
- var shape = obj.shape;
- var cfg = self.getDrawCfg(obj);
- if (isArray(obj.y)) {
- var hasStack = self.hasAdjust('stack');
- each(obj.y, function (y, idx) {
- cfg.y = y;
- if (!hasStack || idx !== 0) {
- self.drawShape(shape, obj, cfg, container, shapeFactory);
- }
- });
- } else if (!isNil(obj.y)) {
- self.drawShape(shape, obj, cfg, container, shapeFactory);
- }
- });
- }
- }
- Geom.Point = Point$1;
- var Line$2 = Shape$1.registerFactory('line', {
- defaultShapeType: 'line'
- });
- function getStyle$1(cfg) {
- var style = {
- strokeStyle: cfg.color
- };
- if (cfg.size >= 0) {
- style.lineWidth = cfg.size;
- }
- mix(style, cfg.style);
- return mix({}, Global.shape.line, style);
- }
- function drawLines(cfg, container, style, smooth) {
- var points = cfg.points;
- if (points.length && isArray(points[0].y)) {
- var topPoints = [];
- var bottomPoints = [];
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- var tmp = splitPoints(point);
- bottomPoints.push(tmp[0]);
- topPoints.push(tmp[1]);
- }
- if (cfg.isInCircle) {
- topPoints.push(topPoints[0]);
- bottomPoints.push(bottomPoints[0]);
- }
- if (cfg.isStack) {
- return container.addShape('Polyline', {
- className: 'line',
- attrs: mix({
- points: topPoints,
- smooth
- }, style)
- });
- }
- var topShape = container.addShape('Polyline', {
- className: 'line',
- attrs: mix({
- points: topPoints,
- smooth
- }, style)
- });
- var bottomShape = container.addShape('Polyline', {
- className: 'line',
- attrs: mix({
- points: bottomPoints,
- smooth
- }, style)
- });
- return [topShape, bottomShape];
- }
- if (cfg.isInCircle) {
- points.push(points[0]);
- }
- return container.addShape('Polyline', {
- className: 'line',
- attrs: mix({
- points,
- smooth
- }, style)
- });
- }
- var SHAPES$1 = ['line', 'smooth', 'dash'];
- each(SHAPES$1, function (shapeType) {
- Shape$1.registerShape('line', shapeType, {
- draw(cfg, container) {
- var smooth = shapeType === 'smooth';
- var style = getStyle$1(cfg);
- if (shapeType === 'dash') {
- style.lineDash = Global.lineDash;
- }
- return drawLines(cfg, container, style, smooth);
- }
- });
- });
- class Path extends Geom {
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'path';
- cfg.shapeType = 'line';
- return cfg;
- }
- getDrawCfg(obj) {
- var cfg = super.getDrawCfg(obj);
- cfg.isStack = this.hasAdjust('stack');
- return cfg;
- }
- draw(data, shapeFactory) {
- var self = this;
- var container = self.get('container');
- var yScale = self.getYScale();
- var connectNulls = self.get('connectNulls');
- var splitArrayObj = splitArray(data, yScale.field, connectNulls);
- var cfg = this.getDrawCfg(data[0]);
- cfg.origin = data;
- each(splitArrayObj, function (subData, splitedIndex) {
- cfg.splitedIndex = splitedIndex;
- cfg.points = subData;
- self.drawShape(cfg.shape, data[0], cfg, container, shapeFactory);
- });
- }
- }
- Geom.Path = Path;
- class Line$3 extends Path {
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'line';
- cfg.sortable = true;
- return cfg;
- }
- }
- Geom.Line = Line$3;
- function equals(v1, v2) {
- return Math.abs(v1 - v2) < 0.00001;
- }
- function notEmpty(value) {
- return !isNaN(value) && !isNil(value);
- }
- function filterPoints(points) {
- var filteredPoints = []; // filter the point which x or y is NaN
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- if (notEmpty(point.x) && notEmpty(point.y)) {
- filteredPoints.push(point);
- }
- }
- return filteredPoints;
- }
- function equalsCenter(points, center) {
- var eqls = true;
- each(points, function (point) {
- if (!equals(point.x, center.x) || !equals(point.y, center.y)) {
- eqls = false;
- return false;
- }
- });
- return eqls;
- }
- function drawRectShape(topPoints, bottomPoints, container, style, isSmooth) {
- var shape;
- var points = topPoints.concat(bottomPoints);
- if (isSmooth) {
- shape = container.addShape('Custom', {
- className: 'area',
- attrs: mix({
- points
- }, style),
- createPath(context) {
- var constaint = [[0, 0], [1, 1]];
- var points = filterPoints(this._attrs.attrs.points);
- var pointsLen = points.length;
- var topPoints = points.slice(0, pointsLen / 2);
- var bottomPoints = points.slice(pointsLen / 2, pointsLen);
- var topSps = catmullRom2bezier(topPoints, false, constaint);
- context.beginPath();
- context.moveTo(topPoints[0].x, topPoints[0].y);
- for (var i = 0, n = topSps.length; i < n; i++) {
- var sp = topSps[i];
- context.bezierCurveTo(sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]);
- }
- if (bottomPoints.length) {
- var bottomSps = catmullRom2bezier(bottomPoints, false, constaint);
- context.lineTo(bottomPoints[0].x, bottomPoints[0].y);
- for (var _i = 0, _n = bottomSps.length; _i < _n; _i++) {
- var _sp = bottomSps[_i];
- context.bezierCurveTo(_sp[1], _sp[2], _sp[3], _sp[4], _sp[5], _sp[6]);
- }
- }
- context.closePath();
- },
- calculateBox() {
- var points = filterPoints(this._attrs.attrs.points);
- return getBBoxFromPoints(points);
- }
- });
- } else {
- shape = container.addShape('Polyline', {
- className: 'area',
- attrs: mix({
- points
- }, style)
- });
- }
- return shape;
- }
- function drawShape$1(cfg, container, isSmooth) {
- var self = this;
- var points = cfg.points;
- var topPoints = [];
- var bottomPoints = [];
- each(points, function (point) {
- bottomPoints.push(point[0]);
- topPoints.push(point[1]);
- });
- var style = mix({
- fillStyle: cfg.color
- }, Global.shape.area, cfg.style);
- bottomPoints.reverse();
- topPoints = self.parsePoints(topPoints);
- bottomPoints = self.parsePoints(bottomPoints);
- if (cfg.isInCircle) {
- topPoints.push(topPoints[0]);
- bottomPoints.unshift(bottomPoints[bottomPoints.length - 1]);
- if (equalsCenter(bottomPoints, cfg.center)) {
- bottomPoints = [];
- }
- }
- return drawRectShape(topPoints, bottomPoints, container, style, isSmooth);
- }
- var Area = Shape$1.registerFactory('area', {
- defaultShapeType: 'area',
- getDefaultPoints(obj) {
- var x = obj.x;
- var y = obj.y;
- var y0 = obj.y0;
- y = isArray(y) ? y : [y0, y];
- var points = [];
- points.push({
- x,
- y: y[0]
- }, {
- x,
- y: y[1]
- });
- return points;
- }
- });
- var SHAPES$2 = ['area', 'smooth'];
- each(SHAPES$2, function (shapeType) {
- Shape$1.registerShape('area', shapeType, {
- draw(cfg, container) {
- var smooth = shapeType === 'smooth';
- return drawShape$1.call(this, cfg, container, smooth);
- }
- });
- });
- /**
- * @fileOverview area geometry
- * @author dxq613 @gmail.com
- * @author sima.zhang1990@gmail.com
- */
- class Area$1 extends Geom {
- /**
- * get the default configuration
- * @protected
- * @return {Object} return the result
- */
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'area';
- cfg.shapeType = 'area';
- cfg.generatePoints = true;
- cfg.sortable = true;
- return cfg;
- }
- draw(data, shapeFactory) {
- var self = this;
- var container = self.get('container');
- var cfg = this.getDrawCfg(data[0]);
- var yScale = self.getYScale();
- var connectNulls = self.get('connectNulls');
- var splitArrayfn = splitArray(data, yScale.field, connectNulls);
- cfg.origin = data;
- each(splitArrayfn, function (subData, splitedIndex) {
- cfg.splitedIndex = splitedIndex;
- var points = subData.map(function (obj) {
- return obj.points;
- });
- cfg.points = points;
- self.drawShape(cfg.shape, data[0], cfg, container, shapeFactory);
- });
- }
- }
- Geom.Area = Area$1;
- /**
- * @fileOverview Utility for calculate the with ratui in x axis
- * @author sima.zhang1990@gmail.com
- * @author dxq613@gmail.com
- */
- var SizeMixin = {
- initEvent() {
- var _this = this;
- var chart = this.get('chart');
- if (!chart) {
- return;
- }
- chart.on(EVENT_AFTER_SIZE_CHANGE, function () {
- _this.set('_width', null);
- });
- },
- getDefaultSize() {
- var defaultSize = this.get('defaultSize');
- if (!defaultSize) {
- var coord = this.get('coord');
- var xScale = this.getXScale();
- var dataArray = this.get('dataArray');
- var values = uniq(xScale.values);
- var count = values.length;
- var range = xScale.range;
- var normalizeSize = 1 / count;
- var widthRatio = 1;
- if (coord && coord.isPolar) {
- if (coord.transposed && count > 1) {
- widthRatio = Global.widthRatio.multiplePie;
- } else {
- widthRatio = Global.widthRatio.rose;
- }
- } else {
- if (xScale.isLinear) {
- normalizeSize *= range[1] - range[0];
- }
- widthRatio = Global.widthRatio.column;
- }
- normalizeSize *= widthRatio;
- if (this.hasAdjust('dodge')) {
- normalizeSize = normalizeSize / dataArray.length;
- }
- defaultSize = normalizeSize;
- this.set('defaultSize', defaultSize);
- }
- return defaultSize;
- },
- getDimWidth(dimName) {
- var coord = this.get('coord');
- var start = coord.convertPoint({
- x: 0,
- y: 0
- });
- var end = coord.convertPoint({
- x: dimName === 'x' ? 1 : 0,
- y: dimName === 'x' ? 0 : 1
- });
- var width = 0;
- if (start && end) {
- width = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2));
- }
- return width;
- },
- _getWidth() {
- var width = this.get('_width');
- if (!width) {
- var coord = this.get('coord');
- if (coord && coord.isPolar && !coord.transposed) {
- width = (coord.endAngle - coord.startAngle) * coord.circleRadius;
- } else {
- width = this.getDimWidth('x');
- }
- this.set('_width', width);
- }
- return width;
- },
- _toNormalizedSize(size) {
- var width = this._getWidth();
- return size / width;
- },
- _toCoordSize(normalizeSize) {
- var width = this._getWidth();
- return width * normalizeSize;
- },
- getNormalizedSize(obj) {
- var size = this.getAttrValue('size', obj);
- if (isNil(size)) {
- size = this.getDefaultSize();
- } else {
- size = this._toNormalizedSize(size);
- }
- return size;
- },
- getSize(obj) {
- var size = this.getAttrValue('size', obj);
- if (isNil(size)) {
- var normalizeSize = this.getDefaultSize();
- size = this._toCoordSize(normalizeSize);
- }
- return size;
- }
- };
- function getRectPoints(cfg) {
- var {
- x,
- y,
- y0,
- size
- } = cfg;
- var ymin = y0;
- var ymax = y;
- if (isArray(y)) {
- ymax = y[1];
- ymin = y[0];
- }
- var xmin;
- var xmax;
- if (isArray(x)) {
- xmin = x[0];
- xmax = x[1];
- } else {
- xmin = x - size / 2;
- xmax = x + size / 2;
- }
- return [{
- x: xmin,
- y: ymin
- }, {
- x: xmin,
- y: ymax
- }, {
- x: xmax,
- y: ymax
- }, {
- x: xmax,
- y: ymin
- }];
- }
- function getRectRange(points) {
- var xValues = [];
- var yValues = [];
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- xValues.push(point.x);
- yValues.push(point.y);
- }
- var xMin = Math.min.apply(null, xValues);
- var yMin = Math.min.apply(null, yValues);
- var xMax = Math.max.apply(null, xValues);
- var yMax = Math.max.apply(null, yValues);
- return {
- x: xMin,
- y: yMin,
- width: xMax - xMin,
- height: yMax - yMin
- };
- }
- function getMiddlePoint(a, b) {
- var x = (a.x - b.x) / 2 + b.x;
- var y = (a.y - b.y) / 2 + b.y;
- return {
- x,
- y
- };
- }
- var Interval = Shape$1.registerFactory('interval', {
- defaultShapeType: 'rect',
- getDefaultPoints(cfg) {
- return getRectPoints(cfg);
- }
- });
- Shape$1.registerShape('interval', 'rect', {
- draw(cfg, container) {
- var points = this.parsePoints(cfg.points);
- var style = mix({
- fill: cfg.color
- }, Global.shape.interval, cfg.style);
- if (cfg.isInCircle) {
- var newPoints = points.slice(0);
- if (this._coord.transposed) {
- newPoints = [points[0], points[3], points[2], points[1]];
- }
- var {
- x,
- y
- } = cfg.center;
- var v = [1, 0];
- var v0 = [newPoints[0].x - x, newPoints[0].y - y];
- var v1 = [newPoints[1].x - x, newPoints[1].y - y];
- var v2 = [newPoints[2].x - x, newPoints[2].y - y];
- var startAngle = Vector2.angleTo(v, v1);
- var endAngle = Vector2.angleTo(v, v2);
- var r0 = Vector2.length(v0);
- var r = Vector2.length(v1);
- if (startAngle >= 1.5 * Math.PI) {
- startAngle = startAngle - 2 * Math.PI;
- }
- if (endAngle >= 1.5 * Math.PI) {
- endAngle = endAngle - 2 * Math.PI;
- }
- return container.addShape('Sector', {
- className: 'interval',
- attrs: mix({
- x,
- y,
- r,
- r0,
- startAngle,
- endAngle
- }, style)
- });
- }
- var rectCfg = getRectRange(points);
- return container.addShape('rect', {
- className: 'interval',
- attrs: mix(rectCfg, style)
- });
- }
- }); // 金字塔 和 漏斗图
- ['pyramid', 'funnel'].forEach(function (shapeType) {
- Shape$1.registerShape('interval', shapeType, {
- getPoints(cfg) {
- cfg.size = cfg.size * 2; // 漏斗图的 size 是柱状图的两倍
- return getRectPoints(cfg);
- },
- draw(cfg, container) {
- var points = this.parsePoints(cfg.points);
- var nextPoints = this.parsePoints(cfg.nextPoints);
- var polygonPoints = null;
- if (nextPoints) {
- polygonPoints = [points[0], points[1], nextPoints[1], nextPoints[0]];
- } else {
- polygonPoints = [points[0], points[1]]; // pyramid 顶部是三角形,所以取中心点就好了,funnel顶部是长方形
- if (shapeType === 'pyramid') {
- polygonPoints.push(getMiddlePoint(points[2], points[3]));
- } else {
- polygonPoints.push(points[2], points[3]);
- }
- }
- var attrs = mix({
- fill: cfg.color,
- points: polygonPoints
- }, Global.shape.interval, cfg.style);
- return container.addShape('polygon', {
- className: 'interval',
- attrs
- });
- }
- });
- });
- class Interval$1 extends Geom {
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'interval';
- cfg.shapeType = 'interval';
- cfg.generatePoints = true;
- return cfg;
- }
- constructor(cfg) {
- super(cfg);
- mix(this, SizeMixin);
- }
- init() {
- super.init(); // 绑定事件
- this.initEvent();
- }
- createShapePointsCfg(obj) {
- var cfg = super.createShapePointsCfg(obj);
- cfg.size = this.getNormalizedSize(obj);
- return cfg;
- }
- clearInner() {
- super.clearInner();
- this.set('defaultSize', null);
- }
- }
- Geom.Interval = Interval$1;
- var Polygon$1 = Shape$1.registerFactory('polygon', {
- defaultShapeType: 'polygon',
- getDefaultPoints(pointInfo) {
- var points = [];
- var {
- x,
- y
- } = pointInfo;
- for (var i = 0, len = x.length; i < len; i++) {
- points.push({
- x: x[i],
- y: y[i]
- });
- }
- return points;
- }
- });
- Shape$1.registerShape('polygon', 'polygon', {
- draw(cfg, container) {
- var points = this.parsePoints(cfg.points);
- var style = mix({
- fill: cfg.color,
- points
- }, cfg.style);
- return container.addShape('Polygon', {
- className: 'polygon',
- attrs: style
- });
- }
- });
- class Polygon$2 extends Geom {
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'polygon';
- cfg.shapeType = 'polygon';
- cfg.generatePoints = true;
- return cfg;
- }
- createShapePointsCfg(obj) {
- var cfg = super.createShapePointsCfg(obj);
- var self = this;
- var x = cfg.x;
- var y = cfg.y;
- var temp;
- if (!(isArray(x) && isArray(y))) {
- var xScale = self.getXScale();
- var yScale = self.getYScale();
- var xCount = xScale.values ? xScale.values.length : xScale.ticks.length;
- var yCount = yScale.values ? yScale.values.length : yScale.ticks.length;
- var xOffset = 0.5 * 1 / xCount;
- var yOffset = 0.5 * 1 / yCount;
- if (xScale.isCategory && yScale.isCategory) {
- x = [x - xOffset, x - xOffset, x + xOffset, x + xOffset];
- y = [y - yOffset, y + yOffset, y + yOffset, y - yOffset];
- } else if (isArray(x)) {
- temp = x;
- x = [temp[0], temp[0], temp[1], temp[1]];
- y = [y - yOffset / 2, y + yOffset / 2, y + yOffset / 2, y - yOffset / 2];
- } else if (isArray(y)) {
- temp = y;
- y = [temp[0], temp[1], temp[1], temp[0]];
- x = [x - xOffset / 2, x - xOffset / 2, x + xOffset / 2, x + xOffset / 2];
- }
- cfg.x = x;
- cfg.y = y;
- }
- return cfg;
- }
- }
- Geom.Polygon = Polygon$2;
- function _sortValue(value) {
- var sorted = value.sort(function (a, b) {
- return a < b ? 1 : -1;
- });
- var length = sorted.length;
- if (length < 4) {
- var min = sorted[length - 1];
- for (var i = 0; i < 4 - length; i++) {
- sorted.push(min);
- }
- }
- return sorted;
- } // from left bottom corner, and clockwise
- function getCandlePoints(x, y, width) {
- var yValues = _sortValue(y);
- var points = [{
- x,
- y: yValues[0]
- }, {
- x,
- y: yValues[1]
- }, {
- x: x - width / 2,
- y: yValues[2]
- }, {
- x: x - width / 2,
- y: yValues[1]
- }, {
- x: x + width / 2,
- y: yValues[1]
- }, {
- x: x + width / 2,
- y: yValues[2]
- }, {
- x,
- y: yValues[2]
- }, {
- x,
- y: yValues[3]
- }];
- return points;
- }
- var Schema = Shape$1.registerFactory('schema', {});
- Shape$1.registerShape('schema', 'candle', {
- getPoints(cfg) {
- return getCandlePoints(cfg.x, cfg.y, cfg.size);
- },
- draw(cfg, container) {
- var points = this.parsePoints(cfg.points);
- var style = mix({
- stroke: cfg.color,
- fill: cfg.color,
- lineWidth: 1
- }, cfg.style);
- return container.addShape('Custom', {
- className: 'schema',
- attrs: style,
- createPath(ctx) {
- ctx.beginPath();
- ctx.moveTo(points[0].x, points[0].y);
- ctx.lineTo(points[1].x, points[1].y);
- ctx.moveTo(points[2].x, points[2].y);
- for (var i = 3; i < 6; i++) {
- ctx.lineTo(points[i].x, points[i].y);
- }
- ctx.closePath();
- ctx.moveTo(points[6].x, points[6].y);
- ctx.lineTo(points[7].x, points[7].y);
- }
- });
- }
- });
- class Schema$1 extends Geom {
- getDefaultCfg() {
- var cfg = super.getDefaultCfg();
- cfg.type = 'schema';
- cfg.shapeType = 'schema';
- cfg.generatePoints = true;
- return cfg;
- }
- constructor(cfg) {
- super(cfg);
- mix(this, SizeMixin);
- }
- init() {
- super.init(); // 绑定事件
- this.initEvent();
- }
- createShapePointsCfg(obj) {
- var cfg = super.createShapePointsCfg(obj);
- cfg.size = this.getNormalizedSize(obj);
- return cfg;
- }
- clearInner() {
- super.clearInner();
- this.set('defaultSize', null);
- }
- }
- Geom.Schema = Schema$1;
- var toString$3 = {}.toString;
- var isType$1 = function isType(value, type) {
- return toString$3.call(value) === '[object ' + type + ']';
- };
- var isType_1 = isType$1;
- var isArray$1 = Array.isArray ? Array.isArray : function (value) {
- return isType_1(value, 'Array');
- };
- var isArray_1 = isArray$1;
- // isFinite,
- var isNil$1 = function isNil(value) {
- /**
- * isNil(null) => true
- * isNil() => true
- */
- return value === null || value === undefined;
- };
- var isNil_1 = isNil$1;
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Stack =
- /*#__PURE__*/
- function (_Adjust) {
- _inheritsLoose(Stack, _Adjust);
- function Stack() {
- return _Adjust.apply(this, arguments) || this;
- }
- var _proto = Stack.prototype;
- _proto._initDefaultCfg = function _initDefaultCfg() {
- this.xField = null; // 调整对应的 x 方向对应的字段名称
- this.yField = null; // 调整对应的 y 方向对应的字段名称
- };
- _proto.processAdjust = function processAdjust(dataArray) {
- this.processStack(dataArray);
- };
- _proto.processStack = function processStack(dataArray) {
- var self = this;
- var xField = self.xField;
- var yField = self.yField;
- var count = dataArray.length;
- var stackCache = {
- positive: {},
- negative: {}
- }; // 层叠顺序翻转
- if (self.reverseOrder) {
- dataArray = dataArray.slice(0).reverse();
- }
- for (var i = 0; i < count; i++) {
- var data = dataArray[i];
- for (var j = 0, len = data.length; j < len; j++) {
- var item = data[j];
- var x = item[xField] || 0;
- var y = item[yField];
- var xkey = x.toString();
- y = isArray_1(y) ? y[1] : y;
- if (!isNil_1(y)) {
- var direction = y >= 0 ? 'positive' : 'negative';
- if (!stackCache[direction][xkey]) {
- stackCache[direction][xkey] = 0;
- }
- item[yField] = [stackCache[direction][xkey], y + stackCache[direction][xkey]];
- stackCache[direction][xkey] += y;
- }
- }
- }
- };
- return Stack;
- }(base);
- base.Stack = Stack;
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- var isObject$1 = function isObject(value) {
- /**
- * isObject({}) => true
- * isObject([1, 2, 3]) => true
- * isObject(Function) => true
- * isObject(null) => false
- */
- var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
- return value !== null && type === 'object' || type === 'function';
- };
- var isObject_1 = isObject$1;
- var each$1 = function each(elements, func) {
- if (!elements) {
- return;
- }
- var rst = void 0;
- if (isArray_1(elements)) {
- for (var i = 0, len = elements.length; i < len; i++) {
- rst = func(elements[i], i);
- if (rst === false) {
- break;
- }
- }
- } else if (isObject_1(elements)) {
- for (var k in elements) {
- if (elements.hasOwnProperty(k)) {
- rst = func(elements[k], k);
- if (rst === false) {
- break;
- }
- }
- }
- }
- };
- var each_1 = each$1;
- function _inheritsLoose$1(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var MARGIN_RATIO = 1 / 2;
- var DODGE_RATIO = 1 / 2;
- var Dodge =
- /*#__PURE__*/
- function (_Adjust) {
- _inheritsLoose$1(Dodge, _Adjust);
- function Dodge() {
- return _Adjust.apply(this, arguments) || this;
- }
- var _proto = Dodge.prototype;
- _proto._initDefaultCfg = function _initDefaultCfg() {
- /**
- * 调整过程中,2个数据的间距
- * @type {Number}
- */
- this.marginRatio = MARGIN_RATIO;
- /**
- * 调整占单位宽度的比例,例如:占2个分类间距的 1/2
- * @type {Number}
- */
- this.dodgeRatio = DODGE_RATIO;
- this.adjustNames = ['x', 'y']; // 调整的维度,默认,x,y都做调整
- };
- _proto.getDodgeOffset = function getDodgeOffset(range, index, count) {
- var self = this;
- var pre = range.pre;
- var next = range.next;
- var tickLength = next - pre;
- var width = tickLength * self.dodgeRatio / count;
- var margin = self.marginRatio * width;
- var offset = 1 / 2 * (tickLength - count * width - (count - 1) * margin) + ((index + 1) * width + index * margin) - 1 / 2 * width - 1 / 2 * tickLength;
- return (pre + next) / 2 + offset;
- };
- _proto.processAdjust = function processAdjust(dataArray) {
- var self = this;
- var count = dataArray.length;
- var xField = self.xField;
- each_1(dataArray, function (data, index) {
- for (var i = 0, len = data.length; i < len; i++) {
- var obj = data[i];
- var value = obj[xField];
- var range = {
- pre: len === 1 ? value - 1 : value - 0.5,
- next: len === 1 ? value + 1 : value + 0.5
- };
- var dodgeValue = self.getDodgeOffset(range, index, count);
- obj[xField] = dodgeValue;
- }
- });
- };
- return Dodge;
- }(base);
- base.Dodge = Dodge;
- /**
- * 是否为函数
- * @param {*} fn 对象
- * @return {Boolean} 是否函数
- */
- var isFunction$1 = function isFunction(value) {
- return isType_1(value, 'Function');
- };
- var isFunction_1 = isFunction$1;
- /**
- * @param {Array} arr The array to iterate over.
- * @param {Function} [fn] The iteratee invoked per element.
- * @return {*} Returns the maximum value.
- * @example
- *
- * var objects = [{ 'n': 1 }, { 'n': 2 }];
- *
- * maxBy(objects, function(o) { return o.n; });
- * // => { 'n': 2 }
- *
- * maxBy(objects, 'n');
- * // => { 'n': 2 }
- */
- var maxBy$1 = function maxBy(arr, fn) {
- if (!isArray_1(arr)) {
- return undefined;
- }
- var max = arr[0];
- var maxData = void 0;
- if (isFunction_1(fn)) {
- maxData = fn(arr[0]);
- } else {
- maxData = arr[0][fn];
- }
- var data = void 0;
- each_1(arr, function (val) {
- if (isFunction_1(fn)) {
- data = fn(val);
- } else {
- data = val[fn];
- }
- if (data > maxData) {
- max = val;
- maxData = data;
- }
- });
- return max;
- };
- var maxBy_1 = maxBy$1;
- var merge$1 = function merge(dataArray) {
- var rst = [];
- for (var i = 0; i < dataArray.length; i++) {
- rst = rst.concat(dataArray[i]);
- }
- return rst;
- };
- var merge_1 = merge$1;
- function _inheritsLoose$2(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var ArrayUtil = {
- merge: merge_1
- };
- var Symmetric =
- /*#__PURE__*/
- function (_Adjust) {
- _inheritsLoose$2(Symmetric, _Adjust);
- function Symmetric() {
- return _Adjust.apply(this, arguments) || this;
- }
- var _proto = Symmetric.prototype;
- _proto._initDefaultCfg = function _initDefaultCfg() {
- this.xField = null; // 调整对应的 x 方向对应的字段名称
- this.yField = null; // 调整对应的 y 方向对应的字段名称
- this.cacheMax = null; // 缓存的最大值
- this.adjustNames = ['y']; // Only support stack y
- this.groupFields = null; // 参与分组的数据维度
- }; // 获取最大的y值
- _proto._getMax = function _getMax(dim) {
- var self = this;
- var mergeData = self.mergeData;
- var maxRecord = maxBy_1(mergeData, function (obj) {
- var value = obj[dim];
- if (isArray_1(value)) {
- return Math.max.apply(null, value);
- }
- return value;
- });
- var maxValue = maxRecord[dim];
- var max = isArray_1(maxValue) ? Math.max.apply(null, maxValue) : maxValue;
- return max;
- }; // 获取每个字段最大的值
- _proto._getXValuesMax = function _getXValuesMax() {
- var self = this;
- var yField = self.yField;
- var xField = self.xField;
- var cache = {};
- var mergeData = self.mergeData;
- each_1(mergeData, function (obj) {
- var xValue = obj[xField];
- var yValue = obj[yField];
- var max = isArray_1(yValue) ? Math.max.apply(null, yValue) : yValue;
- cache[xValue] = cache[xValue] || 0;
- if (cache[xValue] < max) {
- cache[xValue] = max;
- }
- });
- return cache;
- }; // 入口函数
- _proto.processAdjust = function processAdjust(dataArray) {
- var self = this;
- var mergeData = ArrayUtil.merge(dataArray);
- self.mergeData = mergeData;
- self._processSymmetric(dataArray);
- self.mergeData = null;
- }; // 处理对称
- _proto._processSymmetric = function _processSymmetric(dataArray) {
- var self = this;
- var xField = self.xField;
- var yField = self.yField;
- var max = self._getMax(yField);
- var first = dataArray[0][0];
- var cache;
- if (first && isArray_1(first[yField])) {
- cache = self._getXValuesMax();
- }
- each_1(dataArray, function (data) {
- each_1(data, function (obj) {
- var value = obj[yField];
- var offset;
- if (isArray_1(value)) {
- var xValue = obj[xField];
- var valueMax = cache[xValue];
- offset = (max - valueMax) / 2;
- var tmp = [];
- /* eslint-disable no-loop-func */
- each_1(value, function (subVal) {
- // 多个字段
- tmp.push(offset + subVal);
- });
- /* eslint-enable no-loop-func */
- obj[yField] = tmp;
- } else {
- offset = (max - value) / 2;
- obj[yField] = [offset, value + offset];
- }
- });
- });
- };
- return Symmetric;
- }(base);
- base.Symmetric = Symmetric;
- class Polar extends Base$1 {
- _initDefaultCfg() {
- this.type = 'polar';
- this.startAngle = -Math.PI / 2;
- this.endAngle = Math.PI * 3 / 2;
- this.inner = 0;
- this.innerRadius = 0; // alias
- this.isPolar = true;
- this.transposed = false;
- this.center = null;
- this.radius = null; // relative, 0 ~ 1
- }
- init(start, end) {
- super.init(start, end);
- var self = this;
- var inner = self.inner || self.innerRadius;
- var width = Math.abs(end.x - start.x);
- var height = Math.abs(end.y - start.y);
- var maxRadius;
- var center;
- if (self.startAngle === -Math.PI && self.endAngle === 0) {
- maxRadius = Math.min(width / 2, height);
- center = {
- x: (start.x + end.x) / 2,
- y: start.y
- };
- } else {
- maxRadius = Math.min(width, height) / 2;
- center = {
- x: (start.x + end.x) / 2,
- y: (start.y + end.y) / 2
- };
- }
- var radius = self.radius;
- if (radius > 0 && radius <= 1) {
- maxRadius = maxRadius * radius;
- }
- this.x = {
- start: self.startAngle,
- end: self.endAngle
- };
- this.y = {
- start: maxRadius * inner,
- end: maxRadius
- };
- this.center = center;
- this.circleRadius = maxRadius; // the radius value in px
- }
- _convertPoint(point) {
- var self = this;
- var center = self.center;
- var transposed = self.transposed;
- var xDim = transposed ? 'y' : 'x';
- var yDim = transposed ? 'x' : 'y';
- var x = self.x;
- var y = self.y;
- var angle = x.start + (x.end - x.start) * point[xDim];
- var radius = y.start + (y.end - y.start) * point[yDim];
- return {
- x: center.x + Math.cos(angle) * radius,
- y: center.y + Math.sin(angle) * radius
- };
- }
- _invertPoint(point) {
- var self = this;
- var {
- center,
- transposed,
- x,
- y
- } = self;
- var xDim = transposed ? 'y' : 'x';
- var yDim = transposed ? 'x' : 'y';
- var m = [1, 0, 0, 1, 0, 0];
- Matrix.rotate(m, m, x.start);
- var startV = [1, 0];
- Vector2.transformMat2d(startV, startV, m);
- startV = [startV[0], startV[1]];
- var pointV = [point.x - center.x, point.y - center.y];
- if (Vector2.zero(pointV)) {
- return {
- x: 0,
- y: 0
- };
- }
- var theta = Vector2.angleTo(startV, pointV, x.end < x.start);
- if (Math.abs(theta - Math.PI * 2) < 0.001) {
- theta = 0;
- }
- var l = Vector2.length(pointV);
- var percentX = theta / (x.end - x.start);
- percentX = x.end - x.start > 0 ? percentX : -percentX;
- var percentY = (l - y.start) / (y.end - y.start);
- var rst = {};
- rst[xDim] = percentX;
- rst[yDim] = percentY;
- return rst;
- }
- }
- Base$1.Polar = Polar;
- class Circle$1 extends Abastract {
- _initDefaultCfg() {
- super._initDefaultCfg();
- this.startAngle = -Math.PI / 2; // start angle,in radian
- this.endAngle = Math.PI * 3 / 2; // end angle, in radian
- this.radius = null; // radius
- this.center = null; // center
- }
- getOffsetPoint(value) {
- var {
- startAngle,
- endAngle
- } = this;
- var angle = startAngle + (endAngle - startAngle) * value;
- return this._getCirclePoint(angle);
- }
- _getCirclePoint(angle, radius) {
- var self = this;
- var center = self.center;
- radius = radius || self.radius;
- return {
- x: center.x + Math.cos(angle) * radius,
- y: center.y + Math.sin(angle) * radius
- };
- }
- getTextAlignInfo(point, offset) {
- var self = this;
- var offsetVector = self.getOffsetVector(point, offset);
- var align;
- var baseLine = 'middle';
- if (offsetVector[0] > 0) {
- align = 'left';
- } else if (offsetVector[0] < 0) {
- align = 'right';
- } else {
- align = 'center';
- if (offsetVector[1] > 0) {
- baseLine = 'top';
- } else if (offsetVector[1] < 0) {
- baseLine = 'bottom';
- }
- }
- return {
- textAlign: align,
- textBaseline: baseLine
- };
- }
- getAxisVector(point) {
- var center = this.center;
- var factor = this.offsetFactor;
- return [(point.y - center.y) * factor, (point.x - center.x) * -1 * factor];
- }
- drawLine(lineCfg) {
- var {
- center,
- radius,
- startAngle,
- endAngle
- } = this;
- var container = this.getContainer(lineCfg.top);
- container.addShape('arc', {
- className: 'axis-line',
- attrs: mix({
- x: center.x,
- y: center.y,
- r: radius,
- startAngle,
- endAngle
- }, lineCfg)
- });
- }
- }
- Abastract.Circle = Circle$1;
- var KEYWORDS_PERCENT = {
- min: 0,
- median: 0.5,
- max: 1
- };
- class GuideBase {
- _initDefaultCfg() {}
- constructor(cfg) {
- this._initDefaultCfg();
- deepMix(this, cfg);
- }
- _getNormalizedValue(val, scale) {
- var rst;
- if (isNil(KEYWORDS_PERCENT[val])) {
- rst = scale.scale(val);
- } else {
- rst = KEYWORDS_PERCENT[val];
- }
- return rst;
- }
- parsePercentPoint(coord, position) {
- var xPercent = parseFloat(position[0]) / 100;
- var yPercent = parseFloat(position[1]) / 100;
- var start = coord.start;
- var end = coord.end;
- var width = Math.abs(start.x - end.x);
- var height = Math.abs(start.y - end.y);
- var x = width * xPercent + Math.min(start.x, end.x);
- var y = height * yPercent + Math.min(start.y, end.y);
- return {
- x,
- y
- };
- }
- parsePoint(coord, position) {
- var self = this;
- var xScale = self.xScale;
- var yScales = self.yScales;
- if (isFunction(position)) {
- position = position(xScale, yScales); // position 必须是对象
- } // 如果数据格式是 ['50%', '50%'] 的格式
- // fix: 原始数据中可能会包含 'xxx5%xxx' 这样的数据,需要判断下 https://github.com/antvis/f2/issues/590
- if (isString(position[0]) && position[0].indexOf('%') !== -1 && !isNaN(position[0].slice(0, -1))) {
- return this.parsePercentPoint(coord, position);
- }
- var x = self._getNormalizedValue(position[0], xScale);
- var y = self._getNormalizedValue(position[1], yScales[0]);
- var point = coord.convertPoint({
- x,
- y
- });
- if (self.limitInPlot) {
- // limit in chart plotRange
- if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
- return point;
- }
- return null;
- }
- return point;
- }
- /**
- * render the guide component
- * @param {Coord} coord coordinate instance
- * @param {Canvas.Group} group the container
- */
- render()
- /* coord,group */
- {}
- repaint() {
- this.remove();
- var {
- coord,
- container,
- canvas
- } = this;
- if (container && !container.isDestroyed()) {
- this.render(coord, container);
- canvas.draw();
- }
- }
- remove() {
- var {
- element
- } = this;
- element && element.remove(true);
- }
- changeVisible(visible) {
- var self = this;
- self.visible = visible;
- var element = self.element;
- if (!element) return;
- if (element.set) {
- element.set('visible', visible);
- } else {
- element.style.display = visible ? '' : 'none';
- }
- }
- }
- class Arc$1 extends GuideBase {
- _initDefaultCfg() {
- this.type = 'arc';
- /**
- * start point
- * @type {Array | Function}
- */
- this.start = [];
- /**
- * end point
- * @type {Array | Function}
- */
- this.end = [];
- /**
- * style configuration
- * @type {Object}
- */
- this.style = {
- stroke: '#999',
- lineWidth: 1
- };
- }
- render(coord, container) {
- var self = this;
- var start = self.parsePoint(coord, self.start);
- var end = self.parsePoint(coord, self.end);
- if (!start || !end) {
- return;
- }
- var coordCenter = coord.center;
- var radius = Math.sqrt((start.x - coordCenter.x) * (start.x - coordCenter.x) + (start.y - coordCenter.y) * (start.y - coordCenter.y));
- var startAngle = Math.atan2(start.y - coordCenter.y, start.x - coordCenter.x);
- var endAngle = Math.atan2(end.y - coordCenter.y, end.x - coordCenter.x);
- var shape = container.addShape('arc', {
- className: 'guide-arc',
- attrs: mix({
- x: coordCenter.x,
- y: coordCenter.y,
- r: radius,
- startAngle,
- endAngle
- }, self.style)
- });
- self.element = shape;
- return shape;
- }
- }
- GuideBase.Arc = Arc$1;
- function getOffsetFromAlign(alignX, alignY, width, height) {
- var result = [];
- if (alignX === 'left' && alignY === 'top') {
- result[0] = 0;
- result[1] = 0;
- } else if (alignX === 'right' && alignY === 'top') {
- result[0] = -width;
- result[1] = 0;
- } else if (alignX === 'left' && alignY === 'bottom') {
- result[0] = 0;
- result[1] = Math.floor(-height);
- } else if (alignX === 'right' && alignY === 'bottom') {
- result[0] = Math.floor(-width);
- result[1] = Math.floor(-height);
- } else if (alignX === 'right' && alignY === 'middle') {
- result[0] = Math.floor(-width);
- result[1] = Math.floor(-height / 2);
- } else if (alignX === 'left' && alignY === 'middle') {
- result[0] = 0;
- result[1] = Math.floor(-height / 2);
- } else if (alignX === 'center' && alignY === 'bottom') {
- result[0] = Math.floor(-width / 2);
- result[1] = Math.floor(-height);
- } else if (alignX === 'center' && alignY === 'top') {
- result[0] = Math.floor(-width / 2);
- result[1] = 0;
- } else {
- result[0] = Math.floor(-width / 2);
- result[1] = Math.floor(-height / 2);
- }
- return result;
- }
- function modifyCSS(DOM, CSS) {
- for (var key in CSS) {
- if (CSS.hasOwnProperty(key)) {
- DOM.style[key] = CSS[key];
- }
- }
- return DOM;
- }
- function createDom(str) {
- var container = document.createElement('div');
- str = str.replace(/(^\s*)|(\s*$)/g, '');
- container.innerHTML = '' + str;
- return container.childNodes[0];
- }
- class Html extends GuideBase {
- _initDefaultCfg() {
- this.type = 'html';
- /**
- * dom position
- * @type {Object | Array}
- */
- this.position = null;
- /**
- * alignment for horizontal direction,can be 'left','center','right'
- * @type {String}
- */
- this.alignX = 'center';
- /**
- * alignment for vertical direction,can be 'top', 'middle', 'bottom'
- * @type {String}
- */
- this.alignY = 'middle';
- /**
- * offset for horizontal direction
- * @type {Number}
- */
- this.offsetX = null;
- /**
- * offset for vertical direction
- * @type {Number}
- */
- this.offsetY = null;
- /**
- * the html string
- *@type {String | Function}
- */
- this.html = null;
- } // override paint
- render(coord, container) {
- var self = this;
- var position = self.parsePoint(coord, self.position);
- if (!position) {
- return;
- }
- var myNode = createDom(self.html);
- myNode = modifyCSS(myNode, {
- position: 'absolute',
- top: Math.floor(position.y) + 'px',
- left: Math.floor(position.x) + 'px',
- visibility: 'hidden'
- });
- var canvasDom = container.get('canvas').get('el');
- var parentNode = canvasDom.parentNode;
- parentNode = modifyCSS(parentNode, {
- position: 'relative'
- });
- var wrapperNode = createDom('<div class="guideWapper" style="position: absolute;top: 0; left: 0;"></div>');
- parentNode.appendChild(wrapperNode);
- wrapperNode.appendChild(myNode);
- var canvasOffsetTop = canvasDom.offsetTop;
- var canvasOffsetLeft = canvasDom.offsetLeft;
- var {
- alignX,
- alignY,
- offsetX,
- offsetY
- } = self;
- var width = getWidth(myNode);
- var height = getHeight(myNode);
- var newOffset = getOffsetFromAlign(alignX, alignY, width, height);
- position.x = position.x + newOffset[0] + canvasOffsetLeft;
- position.y = position.y + newOffset[1] + canvasOffsetTop;
- if (offsetX) {
- position.x += offsetX;
- }
- if (offsetY) {
- position.y += offsetY;
- }
- modifyCSS(myNode, {
- top: Math.floor(position.y) + 'px',
- left: Math.floor(position.x) + 'px',
- visibility: 'visible'
- });
- self.element = wrapperNode;
- }
- remove() {
- var element = this.element;
- element && element.parentNode && element.parentNode.removeChild(element);
- }
- }
- GuideBase.Html = Html;
- class Line$4 extends GuideBase {
- _initDefaultCfg() {
- this.type = 'line';
- this.start = [];
- this.end = [];
- this.style = {
- stroke: '#000',
- lineWidth: 1
- };
- }
- render(coord, container) {
- var points = [];
- points[0] = this.parsePoint(coord, this.start);
- points[1] = this.parsePoint(coord, this.end);
- if (!points[0] || !points[1]) {
- return;
- }
- var shape = container.addShape('Line', {
- className: 'guide-line',
- attrs: mix({
- x1: points[0].x,
- y1: points[0].y,
- x2: points[1].x,
- y2: points[1].y
- }, this.style)
- });
- this.element = shape;
- return shape;
- }
- }
- GuideBase.Line = Line$4;
- class Rect$2 extends GuideBase {
- _initDefaultCfg() {
- this.type = 'rect';
- this.start = [];
- this.end = [];
- this.style = {
- fill: '#CCD7EB',
- opacity: 0.4
- };
- }
- render(coord, container) {
- var start = this.parsePoint(coord, this.start);
- var end = this.parsePoint(coord, this.end);
- if (!start || !end) {
- return;
- }
- var shape = container.addShape('rect', {
- className: 'guide-rect',
- attrs: mix({
- x: Math.min(start.x, end.x),
- y: Math.min(start.y, end.y),
- width: Math.abs(end.x - start.x),
- height: Math.abs(start.y - end.y)
- }, this.style)
- });
- this.element = shape;
- return shape;
- }
- }
- GuideBase.Rect = Rect$2;
- class Text$1 extends GuideBase {
- _initDefaultCfg() {
- this.type = 'text';
- /**
- * the position of text
- * @type {Function | Array}
- */
- this.position = null;
- /**
- * the display content
- * @type {String}
- */
- this.content = null;
- /**
- * style configuration for text
- * @type {Object}
- */
- this.style = {
- fill: '#000'
- };
- /**
- * offset of horizontal direction
- * @type {Number}
- */
- this.offsetX = 0;
- /**
- * offset of vertical direction
- * @type {Number}
- */
- this.offsetY = 0;
- }
- render(coord, container) {
- var position = this.position;
- var point = this.parsePoint(coord, position);
- if (!point) {
- return;
- }
- var {
- content,
- style,
- offsetX,
- offsetY
- } = this;
- if (offsetX) {
- point.x += offsetX;
- }
- if (offsetY) {
- point.y += offsetY;
- }
- var shape = container.addShape('text', {
- className: 'guide-text',
- attrs: mix({
- x: point.x,
- y: point.y,
- text: content
- }, style)
- });
- this.element = shape;
- return shape;
- }
- }
- GuideBase.Text = Text$1;
- class Tag extends GuideBase {
- _initDefaultCfg() {
- this.type = 'tag';
- this.position = null;
- this.content = null;
- this.direct = 'tl';
- this.autoAdjust = true;
- this.offsetX = 0;
- this.offsetY = 0;
- this.side = 4;
- this.background = {
- padding: 5,
- radius: 2,
- fill: '#1890FF'
- };
- this.textStyle = {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'center',
- textBaseline: 'middle'
- };
- this.withPoint = true;
- this.pointStyle = {
- fill: '#1890FF',
- r: 3,
- lineWidth: 1,
- stroke: '#fff'
- };
- }
- _getDirect(container, point, tagWidth, tagHeight) {
- var direct = this.direct;
- var side = this.side;
- var canvas = container.get('canvas');
- var clientWidth = canvas.get('width');
- var clientHeight = canvas.get('height');
- var {
- x,
- y
- } = point;
- var vertical = direct[0];
- var horizontal = direct[1]; // adjust for vertical direction
- if (vertical === 't' && y - side - tagHeight < 0) {
- vertical = 'b';
- } else if (vertical === 'b' && y + side + tagHeight > clientHeight) {
- vertical = 't';
- } // adjust for horizontal direction
- var diff = vertical === 'c' ? side : 0;
- if (horizontal === 'l' && x - diff - tagWidth < 0) {
- horizontal = 'r';
- } else if (horizontal === 'r' && x + diff + tagWidth > clientWidth) {
- horizontal = 'l';
- } else if (horizontal === 'c') {
- if (tagWidth / 2 + x + diff > clientWidth) {
- horizontal = 'l';
- } else if (x - tagWidth / 2 - diff < 0) {
- horizontal = 'r';
- }
- }
- direct = vertical + horizontal;
- return direct;
- }
- render(coord, container) {
- var position = this.parsePoint(coord, this.position);
- if (!position) {
- return;
- } // 数据不在显示范围内时,x/y 会为NaN
- if (isNaN(position.x) || isNaN(position.y)) {
- return;
- }
- var {
- content,
- background,
- textStyle
- } = this;
- var shapes = [];
- var wrapperContainer = container.addGroup({
- className: 'guide-tag'
- });
- if (this.withPoint) {
- var pointShape = wrapperContainer.addShape('Circle', {
- className: 'guide-tag-point',
- attrs: mix({
- x: position.x,
- y: position.y
- }, this.pointStyle)
- });
- shapes.push(pointShape);
- }
- var tagContainer = wrapperContainer.addGroup(); // create a text shape
- var tagText = tagContainer.addShape('text', {
- className: 'guide-tag-text',
- zIndex: 1,
- attrs: mix({
- x: 0,
- y: 0,
- text: content
- }, textStyle)
- });
- shapes.push(tagText); // create background box
- var textBBox = tagText.getBBox();
- var padding = parsePadding(background.padding);
- var tagWidth = textBBox.width + padding[1] + padding[3];
- var tagHeight = textBBox.height + padding[0] + padding[2];
- var yMin = textBBox.minY - padding[0];
- var xMin = textBBox.minX - padding[3];
- var tagBg = tagContainer.addShape('rect', {
- className: 'guide-tag-bg',
- zIndex: -1,
- attrs: mix({
- x: xMin,
- y: yMin,
- width: tagWidth,
- height: tagHeight
- }, background)
- });
- shapes.push(tagBg);
- var direct = this.autoAdjust ? this._getDirect(container, position, tagWidth, tagHeight) : this.direct;
- var side = this.side;
- var x = position.x + this.offsetX;
- var y = position.y + this.offsetY;
- var arrowPoints;
- var radius = parsePadding(background.radius);
- if (direct === 'tl') {
- arrowPoints = [{
- x: tagWidth + xMin - side - 1,
- y: tagHeight + yMin - 1
- }, // 这个 1 是为了防止出现白边
- {
- x: tagWidth + xMin,
- y: tagHeight + yMin - 1
- }, {
- x: tagWidth + xMin,
- y: tagHeight + side + yMin
- }];
- radius[2] = 0;
- x = x - tagWidth;
- y = y - side - tagHeight;
- } else if (direct === 'cl') {
- arrowPoints = [{
- x: tagWidth + xMin - 1,
- y: (tagHeight - side) / 2 + yMin - 1
- }, {
- x: tagWidth + xMin - 1,
- y: (tagHeight + side) / 2 + yMin + 1
- }, {
- x: tagWidth + side + xMin,
- y: tagHeight / 2 + yMin
- }];
- x = x - tagWidth - side;
- y = y - tagHeight / 2;
- } else if (direct === 'bl') {
- arrowPoints = [{
- x: tagWidth + xMin,
- y: -side + yMin
- }, {
- x: tagWidth + xMin - side - 1,
- y: yMin + 1
- }, {
- x: tagWidth + xMin,
- y: yMin + 1
- }];
- radius[1] = 0;
- x = x - tagWidth;
- y = y + side;
- } else if (direct === 'bc') {
- arrowPoints = [{
- x: tagWidth / 2 + xMin,
- y: -side + yMin
- }, {
- x: (tagWidth - side) / 2 + xMin - 1,
- y: yMin + 1
- }, {
- x: (tagWidth + side) / 2 + xMin + 1,
- y: yMin + 1
- }];
- x = x - tagWidth / 2;
- y = y + side;
- } else if (direct === 'br') {
- arrowPoints = [{
- x: xMin,
- y: yMin - side
- }, {
- x: xMin,
- y: yMin + 1
- }, {
- x: xMin + side + 1,
- y: yMin + 1
- }];
- radius[0] = 0;
- y = y + side;
- } else if (direct === 'cr') {
- arrowPoints = [{
- x: xMin - side,
- y: tagHeight / 2 + yMin
- }, {
- x: xMin + 1,
- y: (tagHeight - side) / 2 + yMin - 1
- }, {
- x: xMin + 1,
- y: (tagHeight + side) / 2 + yMin + 1
- }];
- x = x + side;
- y = y - tagHeight / 2;
- } else if (direct === 'tr') {
- arrowPoints = [{
- x: xMin,
- y: tagHeight + side + yMin
- }, {
- x: xMin,
- y: tagHeight + yMin - 1
- }, {
- x: side + xMin + 1,
- y: tagHeight + yMin - 1
- }];
- radius[3] = 0;
- y = y - tagHeight - side;
- } else if (direct === 'tc') {
- arrowPoints = [{
- x: (tagWidth - side) / 2 + xMin - 1,
- y: tagHeight + yMin - 1
- }, {
- x: (tagWidth + side) / 2 + xMin + 1,
- y: tagHeight + yMin - 1
- }, {
- x: tagWidth / 2 + xMin,
- y: tagHeight + side + yMin
- }];
- x = x - tagWidth / 2;
- y = y - tagHeight - side;
- }
- var sideShape = tagContainer.addShape('Polygon', {
- className: 'guide-tag-side',
- zIndex: 0,
- attrs: {
- points: arrowPoints,
- fill: background.fill
- }
- });
- shapes.push(sideShape);
- tagBg.attr('radius', radius);
- tagContainer.moveTo(x - xMin, y - yMin);
- tagContainer.sort();
- this.element = wrapperContainer;
- return shapes;
- }
- }
- GuideBase.Tag = Tag;
- class Point$2 extends GuideBase {
- _initDefaultCfg() {
- this.type = 'point';
- this.position = null;
- this.offsetX = 0;
- this.offsetY = 0;
- this.style = {
- fill: '#1890FF',
- r: 3,
- lineWidth: 1,
- stroke: '#fff'
- };
- }
- render(coord, container) {
- var position = this.parsePoint(coord, this.position);
- if (!position) return null;
- var shape = container.addShape('Circle', {
- className: 'guide-point',
- attrs: mix({
- x: position.x + this.offsetX,
- y: position.y + this.offsetY
- }, this.style)
- });
- this.element = shape;
- return shape;
- }
- }
- GuideBase.Point = Point$2;
- /**
- * marker shapes,used for tooltip and legend
- */
- var SYMBOLS = {
- circle(x, y, r, ctx) {
- ctx.arc(x, y, r, 0, Math.PI * 2, false);
- },
- square(x, y, r, ctx) {
- ctx.moveTo(x - r, y - r);
- ctx.lineTo(x + r, y - r);
- ctx.lineTo(x + r, y + r);
- ctx.lineTo(x - r, y + r);
- ctx.closePath();
- }
- };
- class Marker extends Shape$2 {
- _initProperties() {
- super._initProperties();
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'marker';
- }
- getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- lineWidth: 0
- };
- }
- createPath(context) {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- radius
- } = attrs;
- var symbol = attrs.symbol || 'circle';
- var method;
- if (isFunction(symbol)) {
- method = symbol;
- } else {
- method = SYMBOLS[symbol];
- }
- context.beginPath();
- method(x, y, radius, context, this);
- }
- calculateBox() {
- var attrs = this.get('attrs');
- var {
- x,
- y,
- radius
- } = attrs;
- return {
- minX: x - radius,
- minY: y - radius,
- maxX: x + radius,
- maxY: y + radius
- };
- }
- }
- var MARKER_RADIUS = 3;
- class List {
- getDefaultCfg() {
- return {
- showTitle: false,
- /**
- * title string
- * @type {?String}
- */
- title: null,
- /**
- * items array
- * @type {?Array}
- */
- items: null,
- /**
- * offset between title and items
- * @type {Number}
- */
- titleGap: 12,
- /**
- * offset between each item
- * @type {Number}
- */
- itemGap: 10,
- /**
- * the offset between each item in vertical direaction
- * @type {Number}
- */
- itemMarginBottom: 12,
- /**
- * the formatter for item text
- * @type {[type]}
- */
- itemFormatter: null,
- itemWidth: null,
- /**
- * offset between marker and text
- * @type {Number}
- */
- wordSpace: 6,
- x: 0,
- y: 0,
- layout: 'horizontal',
- /**
- * the join string of `name` and `value`
- * @type {String}
- */
- joinString: ': '
- };
- }
- constructor(cfg) {
- deepMix(this, this.getDefaultCfg(), cfg);
- this._init();
- this._renderTitle();
- this._renderItems();
- }
- _init() {
- var container = new Group({
- zIndex: this.zIndex || 0
- });
- this.container = container;
- var wrapper = container.addGroup();
- this.wrapper = wrapper;
- var itemsGroup = wrapper.addGroup({
- className: 'itemsGroup'
- });
- this.itemsGroup = itemsGroup;
- if (this.parent) {
- this.parent.add(container);
- }
- }
- _renderTitle(title) {
- title = title || this.title;
- var titleShape = this.titleShape;
- var titleHeight = 0;
- if (this.showTitle && title) {
- if (titleShape && !titleShape.get('destroyed')) {
- titleShape.attr('text', title);
- } else {
- var {
- wrapper,
- titleStyle
- } = this;
- titleShape = wrapper.addShape('text', {
- className: 'title',
- attrs: mix({
- x: 0,
- y: 0,
- text: title
- }, titleStyle)
- });
- this.titleShape = titleShape;
- }
- titleHeight = titleShape.getBBox().height + this.titleGap;
- }
- this._titleHeight = titleHeight;
- }
- _renderItems(items) {
- var self = this;
- items = items || self.items;
- if (!items) {
- return;
- }
- if (self.reversed) {
- items.reverse();
- }
- each(items, function (item, index) {
- self._addItem(item, index);
- });
- if (items.length > 1) {
- this._adjustItems();
- }
- this._renderBackground();
- }
- _renderBackground() {
- var background = this.background;
- if (background) {
- var container = this.container;
- var wrapper = this.wrapper;
- var {
- minX,
- minY,
- width,
- height
- } = wrapper.getBBox();
- var padding = background.padding || [0, 0, 0, 0];
- padding = parsePadding(padding);
- var attrs = mix({
- x: minX - padding[3],
- y: minY - padding[0],
- width: width + padding[1] + padding[3],
- height: height + padding[0] + padding[2]
- }, background);
- var backShape = this.backShape;
- if (backShape) {
- backShape.attr(attrs);
- } else {
- backShape = container.addShape('Rect', {
- zIndex: -1,
- attrs
- });
- }
- this.backShape = backShape;
- container.sort();
- }
- }
- _addItem(item) {
- var itemsGroup = this.itemsGroup;
- var itemGroup = itemsGroup.addGroup({
- name: item.name,
- value: item.value,
- dataValue: item.dataValue,
- checked: item.checked
- });
- var {
- unCheckStyle,
- unCheckColor,
- nameStyle,
- valueStyle,
- wordSpace
- } = this;
- var {
- marker,
- value
- } = item;
- var startX = 0;
- if (unCheckColor) {
- unCheckStyle.fill = unCheckColor;
- }
- if (marker) {
- var radius = marker.radius || MARKER_RADIUS;
- var markerAttrs = mix({
- x: radius,
- y: this._titleHeight
- }, marker);
- if (item.checked === false) {
- mix(markerAttrs, unCheckStyle);
- }
- var markerShape = new Marker({
- className: 'item-marker',
- attrs: markerAttrs
- });
- itemGroup.add(markerShape);
- startX += markerShape.getBBox().width + wordSpace;
- }
- var nameText;
- var name = item.name;
- if (name) {
- var joinString = this.joinString || '';
- name = value ? name + joinString : name;
- nameText = itemGroup.addShape('text', {
- className: 'name',
- attrs: mix({
- x: startX,
- y: this._titleHeight,
- text: this._formatItemValue(name)
- }, nameStyle, item.checked === false ? unCheckStyle : null)
- });
- }
- if (value) {
- var valueX = startX;
- if (nameText) {
- valueX += nameText.getBBox().width;
- }
- itemGroup.addShape('text', {
- className: 'value',
- attrs: mix({
- x: valueX,
- y: this._titleHeight,
- text: value
- }, valueStyle, item.checked === false ? unCheckStyle : null)
- });
- }
- return itemGroup;
- }
- _formatItemValue(value) {
- var formatter = this.itemFormatter;
- if (formatter) {
- value = formatter.call(this, value);
- }
- return value;
- }
- _getMaxItemWidth() {
- var width;
- var itemWidth = this.itemWidth;
- if (isNumber(itemWidth) || isNil(itemWidth)) {
- return itemWidth;
- }
- if (itemWidth === 'auto') {
- var itemsGroup = this.itemsGroup;
- var children = itemsGroup.get('children');
- var count = children.length;
- var maxItemWidth = 0;
- for (var i = 0; i < count; i++) {
- var {
- width: _width
- } = children[i].getBBox();
- maxItemWidth = Math.max(maxItemWidth, _width);
- }
- var maxLength = this.maxLength;
- var itemGap = this.itemGap;
- var twoAvgWidth = (maxLength - itemGap) / 2;
- var threeAvgWidth = (maxLength - itemGap * 2) / 3;
- if (count === 2) {
- width = Math.max(maxItemWidth, twoAvgWidth);
- } else {
- // 1. max <= 3Avg, 3Avg
- // 2. 3Avg < max && max < 2avg, 2avg
- // 3. max > 2avg, max, one column
- if (maxItemWidth <= threeAvgWidth) {
- width = threeAvgWidth;
- } else if (maxItemWidth <= twoAvgWidth) {
- width = twoAvgWidth;
- } else {
- width = maxItemWidth;
- }
- }
- return width;
- }
- }
- _adjustHorizontal() {
- var {
- maxLength,
- itemsGroup
- } = this;
- var children = itemsGroup.get('children');
- var {
- itemGap,
- itemMarginBottom
- } = this;
- var titleHeight = this._titleHeight;
- var row = 0;
- var rowWidth = 0;
- var width;
- var height;
- var itemWidth = this._getMaxItemWidth();
- var legendHitBoxes = [];
- for (var i = 0, len = children.length; i < len; i++) {
- var child = children[i];
- var box = child.getBBox();
- var childHeight = box.height;
- var childWidth = box.width;
- width = itemWidth || childWidth;
- height = childHeight + itemMarginBottom;
- if (width - (maxLength - rowWidth) > 0.0001) {
- row++;
- rowWidth = 0;
- }
- child.moveTo(rowWidth, row * height);
- legendHitBoxes.push({
- x: rowWidth,
- y: row * height + titleHeight - childHeight / 2,
- width: childWidth * 1.375,
- height: childHeight * 1.375
- });
- rowWidth += width + itemGap;
- }
- this.legendHitBoxes = legendHitBoxes;
- return;
- }
- _adjustVertical() {
- var {
- maxLength,
- itemsGroup
- } = this;
- var {
- itemGap,
- itemMarginBottom,
- itemWidth
- } = this;
- var titleHeight = this._titleHeight;
- var children = itemsGroup.get('children');
- var colHeight = 0;
- var width;
- var height;
- var maxItemWidth = 0;
- var totalWidth = 0;
- var legendHitBoxes = [];
- for (var i = 0, length = children.length; i < length; i++) {
- var child = children[i];
- var bbox = child.getBBox();
- width = bbox.width;
- height = bbox.height;
- if (isNumber(itemWidth)) {
- maxItemWidth = itemWidth + itemGap;
- } else if (width > maxItemWidth) {
- maxItemWidth = width + itemGap;
- }
- if (maxLength - colHeight < height) {
- colHeight = 0;
- totalWidth += maxItemWidth;
- child.moveTo(totalWidth, 0);
- legendHitBoxes.push({
- x: totalWidth,
- y: titleHeight - height / 2,
- width: width * 1.375,
- height: height * 1.375
- });
- } else {
- child.moveTo(totalWidth, colHeight);
- legendHitBoxes.push({
- x: totalWidth,
- y: colHeight - height / 2 + titleHeight,
- width: width * 1.375,
- height: height * 1.375
- });
- }
- colHeight += height + itemMarginBottom;
- }
- this.legendHitBoxes = legendHitBoxes;
- return;
- }
- _adjustItems() {
- var layout = this.layout;
- if (layout === 'horizontal') {
- this._adjustHorizontal();
- } else {
- this._adjustVertical();
- }
- }
- moveTo(x, y) {
- this.x = x;
- this.y = y;
- var container = this.container;
- container && container.moveTo(x, y);
- return this;
- }
- setItems(items) {
- this.clearItems();
- this._renderItems(items);
- }
- setTitle(title) {
- this._renderTitle(title);
- }
- clearItems() {
- var itemsGroup = this.itemsGroup;
- itemsGroup.clear();
- }
- getWidth() {
- var container = this.container;
- var bbox = container.getBBox();
- return bbox.width;
- }
- getHeight() {
- var container = this.container;
- var bbox = container.getBBox();
- return bbox.height;
- }
- show() {
- var container = this.container;
- container.show();
- }
- hide() {
- var container = this.container;
- container.hide();
- }
- clear() {
- var container = this.container;
- container.clear();
- container.remove(true);
- }
- }
- class TextBox {
- getDefaultCfg() {
- return {
- x: 0,
- y: 0,
- content: '',
- textStyle: {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'center',
- textBaseline: 'middle',
- fontFamily: 'Arial'
- },
- background: {
- radius: 1,
- fill: 'rgba(0, 0, 0, 0.65)',
- padding: [3, 5]
- },
- width: 0,
- height: 0,
- className: ''
- };
- }
- constructor(cfg) {
- deepMix(this, this.getDefaultCfg(), cfg);
- this._init();
- var {
- content,
- x,
- y
- } = this;
- if (!isNil(content)) {
- this.updateContent(content);
- }
- this.updatePosition(x, y);
- }
- _init() {
- var {
- content,
- textStyle,
- background,
- className,
- visible,
- context
- } = this;
- var container = new Group({
- context,
- className,
- zIndex: 0,
- visible
- });
- var text = container.addShape('Text', {
- className: className + '-text',
- zIndex: 1,
- attrs: mix({
- text: content,
- x: 0,
- y: 0
- }, textStyle)
- });
- var backgroundShape = container.addShape('Rect', {
- className: className + '-bg',
- zIndex: -1,
- attrs: mix({
- x: 0,
- y: 0,
- width: 0,
- height: 0
- }, background)
- });
- container.sort();
- this.container = container;
- this.textShape = text;
- this.backgroundShape = backgroundShape;
- }
- _getBBox() {
- var textShape = this.textShape;
- var background = this.background;
- var textBBox = textShape.getBBox();
- var padding = parsePadding(background.padding);
- var width = textBBox.width + padding[1] + padding[3];
- var height = textBBox.height + padding[0] + padding[2];
- var x = textBBox.minX - padding[3];
- var y = textBBox.minY - padding[0];
- return {
- x,
- y,
- width,
- height
- };
- }
- updateContent(text) {
- var {
- textShape,
- backgroundShape
- } = this;
- if (!isNil(text)) {
- if (!isObject(text)) {
- text = {
- text
- };
- }
- textShape.attr(text); // update box shape
- var {
- x,
- y,
- width: tipWidth,
- height: tipHeight
- } = this._getBBox();
- var width = this.width || tipWidth;
- var height = this.height || tipHeight;
- backgroundShape.attr({
- x,
- y,
- width,
- height
- });
- this._width = width;
- this._height = height;
- this.content = text.text;
- }
- }
- updatePosition(x, y) {
- var container = this.container;
- var {
- x: xMin,
- y: yMin
- } = this._getBBox();
- container.moveTo(x - xMin, y - yMin);
- this.x = x - xMin;
- this.y = y - yMin;
- }
- getWidth() {
- return this._width;
- }
- getHeight() {
- return this._height;
- }
- show() {
- this.container.show();
- }
- hide() {
- this.container.hide();
- }
- clear() {
- var container = this.container;
- container.clear();
- container.remove(true);
- this.container = null;
- this.textShape = null;
- this.backgroundShape = null;
- }
- }
- var GAP = 4;
- /**
- * TODOList:
- * 1. 移除 fixed 参数
- */
- class Tooltip {
- getDefaultCfg() {
- return {
- /**
- * wether show the crosshairs
- * @type {Object}
- */
- showCrosshairs: false,
- /**
- * the style for crosshairs
- * @type {Object}
- */
- crosshairsStyle: {
- stroke: 'rgba(0, 0, 0, 0.25)',
- lineWidth: 1
- },
- /**
- * the type of crosshairs, optional value is 'x', 'y' or 'xy', default is 'y'
- */
- crosshairsType: 'y',
- /**
- * show or hide the x axis tip
- */
- showXTip: false,
- /**
- * show or hide the y axis tip
- */
- showYTip: false,
- xTip: null,
- xTipBackground: {
- radius: 1,
- fill: 'rgba(0, 0, 0, 0.65)',
- padding: [3, 5]
- },
- xTipTextStyle: {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'center',
- textBaseline: 'middle'
- },
- yTip: null,
- yTipBackground: {
- radius: 1,
- fill: 'rgba(0, 0, 0, 0.65)',
- padding: [3, 5]
- },
- yTipTextStyle: {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'center',
- textBaseline: 'middle'
- },
- /**
- * the style for tooltip container's background
- * @type {Object}
- */
- background: null,
- /**
- * layout, can be horizontal or vertical
- * @type {String}
- */
- layout: 'horizontal',
- offsetX: 0,
- offsetY: 0
- };
- }
- constructor(cfg) {
- deepMix(this, this.getDefaultCfg(), cfg);
- var {
- frontPlot,
- custom
- } = this;
- if (!custom) {
- // custom means user do customize
- var container = new List(mix({
- parent: frontPlot,
- zIndex: 3
- }, cfg));
- this.container = container;
- var {
- fixed,
- background
- } = this;
- if (!fixed) {
- this.tooltipArrow = frontPlot.addShape('Polygon', {
- className: 'tooltip-arrow',
- visible: false,
- zIndex: 2,
- attrs: mix({
- points: []
- }, background)
- });
- }
- }
- if (this.showXTip) {
- var {
- xTipBackground,
- xTipTextStyle
- } = this;
- var xTipBox = new TextBox({
- context: frontPlot.get('context'),
- className: 'xTip',
- background: xTipBackground,
- textStyle: xTipTextStyle,
- visible: false
- });
- frontPlot.add(xTipBox.container);
- this.xTipBox = xTipBox;
- }
- if (this.showYTip) {
- var {
- yTipBackground,
- yTipTextStyle
- } = this;
- var yTipBox = new TextBox({
- context: frontPlot.get('context'),
- className: 'yTip',
- background: yTipBackground,
- textStyle: yTipTextStyle,
- visible: false
- });
- frontPlot.add(yTipBox.container);
- this.yTipBox = yTipBox;
- }
- if (this.showCrosshairs) {
- this._renderCrosshairs();
- }
- frontPlot.sort();
- }
- setContent(title, items) {
- this.title = title;
- this.items = items;
- if (!this.custom) {
- var container = this.container;
- container.setTitle(title);
- container.setItems(items);
- }
- }
- setYTipContent(val) {
- var yTip = this.yTip;
- if (isFunction(yTip)) {
- val = yTip(val);
- } else {
- val = mix({
- text: val
- }, yTip);
- }
- this.yTipBox && this.yTipBox.updateContent(val);
- }
- setYTipPosition(pos) {
- var plotRange = this.plotRange;
- var crosshairsShapeX = this.crosshairsShapeX;
- if (this.showYTip) {
- var yTipBox = this.yTipBox;
- var yTipHeight = yTipBox.getHeight();
- var yTipWidth = yTipBox.getWidth();
- var posX = plotRange.tl.x - yTipWidth;
- var posY = pos - yTipHeight / 2;
- if (posY <= plotRange.tl.y) {
- posY = plotRange.tl.y;
- }
- if (posY + yTipHeight >= plotRange.br.y) {
- posY = plotRange.br.y - yTipHeight;
- }
- if (posX < 0) {
- posX = plotRange.tl.x;
- crosshairsShapeX && crosshairsShapeX.attr('x1', plotRange.tl.x + yTipWidth);
- }
- yTipBox.updatePosition(posX, posY);
- }
- }
- setXTipContent(val) {
- var xTip = this.xTip;
- if (isFunction(xTip)) {
- val = xTip(val);
- } else {
- val = mix({
- text: val
- }, xTip);
- }
- this.xTipBox && this.xTipBox.updateContent(val);
- }
- setXTipPosition(pos) {
- var {
- showXTip,
- canvas,
- plotRange,
- xTipBox,
- crosshairsShapeY
- } = this;
- if (showXTip) {
- // const el = canvas.get('el');
- // const canvasHeight = Util.getHeight(el);
- var canvasHeight = canvas.get('height');
- var xTipWidth = xTipBox.getWidth();
- var xTipHeight = xTipBox.getHeight();
- var posX = pos - xTipWidth / 2;
- var posY = plotRange.br.y;
- if (posX <= plotRange.tl.x) {
- posX = plotRange.tl.x;
- }
- if (posX + xTipWidth >= plotRange.tr.x) {
- posX = plotRange.tr.x - xTipWidth;
- }
- if (canvasHeight - posY < xTipHeight) {
- posY -= xTipHeight;
- }
- xTipBox.updatePosition(posX, posY);
- crosshairsShapeY && crosshairsShapeY.attr('y1', posY);
- }
- }
- setXCrosshairPosition(pos) {
- this.crosshairsShapeX && this.crosshairsShapeX.moveTo(0, pos);
- }
- setYCrosshairPosition(pos) {
- this.crosshairsShapeY && this.crosshairsShapeY.moveTo(pos, 0);
- }
- setPosition(items) {
- var {
- container,
- plotRange,
- offsetX,
- offsetY,
- fixed,
- tooltipArrow
- } = this;
- if (!container) {
- return;
- }
- var containerBBox = container.container.getBBox();
- var {
- minX,
- minY,
- width,
- height
- } = containerBBox;
- var {
- tl,
- tr
- } = plotRange;
- var posX = 0;
- var posY = tl.y - height - GAP + offsetY;
- if (fixed) {
- var x = (tl.x + tr.x) / 2;
- posX = x - width / 2 + offsetX;
- } else {
- var _x;
- if (items.length > 1) {
- _x = (items[0].x + items[items.length - 1].x) / 2;
- } else {
- _x = items[0].x;
- }
- posX = _x - width / 2 + offsetX;
- if (posX < tl.x) {
- posX = tl.x;
- }
- if (posX + width > tr.x) {
- posX = tr.x - width;
- }
- if (tooltipArrow) {
- tooltipArrow.attr('points', [{
- x: _x - 3,
- y: tl.y - GAP + offsetY
- }, {
- x: _x + 3,
- y: tl.y - GAP + offsetY
- }, {
- x: _x,
- y: tl.y + offsetY
- }]);
- var backShape = container.backShape;
- var radius = parsePadding(backShape.attr('radius'));
- if (_x === tl.x) {
- radius[3] = 0;
- tooltipArrow.attr('points', [{
- x: tl.x,
- y: tl.y + offsetY
- }, {
- x: tl.x,
- y: tl.y - GAP + offsetY
- }, {
- x: tl.x + GAP,
- y: tl.y - GAP + offsetY
- }]);
- } else if (_x === tr.x) {
- radius[2] = 0;
- tooltipArrow.attr('points', [{
- x: tr.x,
- y: tl.y + offsetY
- }, {
- x: tr.x - GAP,
- y: tl.y - GAP + offsetY
- }, {
- x: tr.x,
- y: tl.y - GAP + offsetY
- }]);
- }
- backShape.attr('radius', radius);
- }
- }
- container.moveTo(posX - minX, posY - minY);
- }
- setMarkers() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var self = this;
- var {
- items,
- style,
- type
- } = cfg;
- var markerGroup = self._getMarkerGroup(type);
- if (type === 'circle') {
- for (var i = 0, length = items.length; i < length; i++) {
- var item = items[i];
- var marker = new Marker({
- className: 'tooltip-circle-marker',
- attrs: mix({
- x: item.x,
- y: item.y,
- stroke: item.color
- }, style)
- });
- markerGroup.add(marker);
- }
- } else {
- markerGroup.addShape('rect', {
- className: 'tooltip-rect-marker',
- attrs: style
- });
- }
- }
- clearMarkers() {
- var markerGroup = this.markerGroup;
- markerGroup && markerGroup.clear();
- }
- show() {
- var crosshairsShapeX = this.crosshairsShapeX;
- var crosshairsShapeY = this.crosshairsShapeY;
- var markerGroup = this.markerGroup;
- var container = this.container;
- var tooltipArrow = this.tooltipArrow;
- var xTipBox = this.xTipBox;
- var yTipBox = this.yTipBox;
- var canvas = this.canvas;
- crosshairsShapeX && crosshairsShapeX.show();
- crosshairsShapeY && crosshairsShapeY.show();
- markerGroup && markerGroup.show();
- container && container.show();
- tooltipArrow && tooltipArrow.show();
- xTipBox && xTipBox.show();
- yTipBox && yTipBox.show();
- canvas.draw();
- }
- hide() {
- var crosshairsShapeX = this.crosshairsShapeX;
- var crosshairsShapeY = this.crosshairsShapeY;
- var markerGroup = this.markerGroup;
- var container = this.container;
- var tooltipArrow = this.tooltipArrow;
- var xTipBox = this.xTipBox;
- var yTipBox = this.yTipBox;
- crosshairsShapeX && crosshairsShapeX.hide();
- crosshairsShapeY && crosshairsShapeY.hide();
- markerGroup && markerGroup.hide();
- container && container.hide();
- tooltipArrow && tooltipArrow.hide();
- xTipBox && xTipBox.hide();
- yTipBox && yTipBox.hide();
- }
- destroy() {
- var crosshairsShapeX = this.crosshairsShapeX;
- var crosshairsShapeY = this.crosshairsShapeY;
- var markerGroup = this.markerGroup;
- var container = this.container;
- var tooltipArrow = this.tooltipArrow;
- var xTipBox = this.xTipBox;
- var yTipBox = this.yTipBox;
- crosshairsShapeX && crosshairsShapeX.remove(true);
- crosshairsShapeY && crosshairsShapeY.remove(true);
- markerGroup && markerGroup.remove(true);
- tooltipArrow && tooltipArrow.remove(true);
- container && container.clear();
- xTipBox && xTipBox.clear();
- yTipBox && yTipBox.clear();
- this.destroyed = true;
- }
- _getMarkerGroup(type) {
- var markerGroup = this.markerGroup;
- if (!markerGroup) {
- if (type === 'circle') {
- markerGroup = this.frontPlot.addGroup({
- zIndex: 1
- });
- this.frontPlot.sort();
- } else {
- markerGroup = this.backPlot.addGroup();
- }
- this.markerGroup = markerGroup;
- } else {
- markerGroup.clear();
- }
- return markerGroup;
- }
- _renderCrosshairs() {
- var {
- crosshairsType,
- crosshairsStyle,
- frontPlot,
- plotRange
- } = this;
- var {
- tl,
- br
- } = plotRange;
- if (directionEnabled(crosshairsType, 'x')) {
- this.crosshairsShapeX = frontPlot.addShape('Line', {
- className: 'tooltip-crosshairs-x',
- zIndex: 0,
- visible: false,
- attrs: mix({
- x1: tl.x,
- y1: 0,
- x2: br.x,
- y2: 0
- }, crosshairsStyle)
- });
- }
- if (directionEnabled(crosshairsType, 'y')) {
- this.crosshairsShapeY = frontPlot.addShape('Line', {
- className: 'tooltip-crosshairs-y',
- zIndex: 0,
- visible: false,
- attrs: mix({
- x1: 0,
- y1: br.y,
- x2: 0,
- y2: tl.y
- }, crosshairsStyle)
- });
- }
- }
- }
- function _defineProperty$2(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- Global.tooltip = deepMix({
- triggerOn: 'press',
- triggerOff: 'pressend',
- alwaysShow: false,
- showTitle: false,
- showCrosshairs: false,
- crosshairsStyle: {
- stroke: 'rgba(0, 0, 0, 0.25)',
- lineWidth: 1
- },
- showTooltipMarker: true,
- background: {
- radius: 1,
- fill: 'rgba(0, 0, 0, 0.65)',
- padding: [3, 5]
- },
- titleStyle: {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'start',
- textBaseline: 'top'
- },
- nameStyle: {
- fontSize: 12,
- fill: 'rgba(255, 255, 255, 0.65)',
- textAlign: 'start',
- textBaseline: 'middle'
- },
- valueStyle: {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'start',
- textBaseline: 'middle'
- },
- showItemMarker: true,
- itemMarkerStyle: {
- radius: 3,
- symbol: 'circle',
- lineWidth: 1,
- stroke: '#fff'
- },
- layout: 'horizontal',
- snap: false
- }, Global.tooltip || {});
- function _getTooltipValueScale(geom) {
- var colorAttr = geom.getAttr('color');
- if (colorAttr) {
- var colorScale = colorAttr.getScale(colorAttr.type);
- if (colorScale.isLinear) {
- return colorScale;
- }
- }
- var xScale = geom.getXScale();
- var yScale = geom.getYScale();
- if (yScale) {
- return yScale;
- }
- return xScale;
- }
- function getTooltipName(geom, origin) {
- var name;
- var nameScale;
- var groupScales = geom._getGroupScales();
- if (groupScales.length) {
- each(groupScales, function (scale) {
- nameScale = scale;
- return false;
- });
- }
- if (nameScale) {
- var field = nameScale.field;
- name = nameScale.getText(origin[field]);
- } else {
- var valueScale = _getTooltipValueScale(geom);
- name = valueScale.alias || valueScale.field;
- }
- return name;
- }
- function getTooltipValue(geom, origin) {
- var scale = _getTooltipValueScale(geom);
- return scale.getText(origin[scale.field]);
- }
- function getTooltipTitle(geom, origin) {
- var position = geom.getAttr('position');
- var field = position.getFields()[0];
- var scale = geom.get('scales')[field];
- return scale.getText(origin[scale.field]);
- }
- function _indexOfArray(items, item) {
- var rst = -1;
- each(items, function (sub, index) {
- if (sub.title === item.title && sub.name === item.name && sub.value === item.value && sub.color === item.color) {
- rst = index;
- return false;
- }
- });
- return rst;
- }
- function _uniqItems(items) {
- var tmp = [];
- each(items, function (item) {
- var index = _indexOfArray(tmp, item);
- if (index === -1) {
- tmp.push(item);
- } else {
- tmp[index] = item;
- }
- });
- return tmp;
- }
- function isEqual$1(arr1, arr2) {
- return JSON.stringify(arr1) === JSON.stringify(arr2);
- }
- class TooltipController {
- constructor(cfg) {
- var _this = this;
- _defineProperty$2(this, "handleShowEvent", function (ev) {
- var chart = _this.chart;
- if (!_this.enable) return;
- var plot = chart.get('plotRange');
- var point = createEvent(ev, chart);
- if (!isPointInPlot(point, plot) && !_this._tooltipCfg.alwaysShow) {
- // not in chart plot
- _this.hideTooltip();
- return;
- }
- var lastTimeStamp = _this.timeStamp;
- var timeStamp = +new Date();
- if (timeStamp - lastTimeStamp > 16) {
- _this.showTooltip(point);
- _this.timeStamp = timeStamp;
- }
- });
- _defineProperty$2(this, "handleHideEvent", function () {
- if (!_this.enable) return;
- _this.hideTooltip();
- });
- this.enable = true;
- this.cfg = {};
- this.tooltip = null;
- this.chart = null;
- this.timeStamp = 0;
- mix(this, cfg);
- var _chart = this.chart;
- var canvas = _chart.get('canvas');
- this.canvas = canvas;
- this.canvasDom = canvas.get('el');
- }
- _setCrosshairsCfg() {
- var self = this;
- var chart = self.chart;
- var defaultCfg = mix({}, Global.tooltip);
- var geoms = chart.get('geoms');
- var shapes = [];
- each(geoms, function (geom) {
- var type = geom.get('type');
- if (shapes.indexOf(type) === -1) {
- shapes.push(type);
- }
- });
- var coordType = chart.get('coord').type;
- if (geoms.length && (coordType === 'cartesian' || coordType === 'rect')) {
- if (shapes.length === 1 && ['line', 'area', 'path', 'point'].indexOf(shapes[0]) !== -1) {
- mix(defaultCfg, {
- showCrosshairs: true
- });
- }
- }
- return defaultCfg;
- }
- _getMaxLength() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var {
- layout,
- plotRange
- } = cfg;
- return layout === 'horizontal' ? plotRange.br.x - plotRange.bl.x : plotRange.bl.y - plotRange.tr.y;
- }
- render() {
- var self = this;
- if (self.tooltip) {
- return;
- }
- var chart = self.chart;
- var canvas = chart.get('canvas');
- var frontPlot = chart.get('frontPlot').addGroup({
- className: 'tooltipContainer',
- zIndex: 10
- });
- var backPlot = chart.get('backPlot').addGroup({
- className: 'tooltipContainer'
- });
- var plotRange = chart.get('plotRange');
- var coord = chart.get('coord');
- var defaultCfg = self._setCrosshairsCfg();
- var cfg = self.cfg; // 通过 chart.tooltip() 接口传入的 tooltip 配置项
- var tooltipCfg = deepMix({
- plotRange,
- frontPlot,
- backPlot,
- canvas,
- fixed: coord.transposed || coord.isPolar
- }, defaultCfg, cfg); // 创建 tooltip 实例需要的配置,不应该修改 this.cfg,即用户传入的配置
- tooltipCfg.maxLength = self._getMaxLength(tooltipCfg);
- this._tooltipCfg = tooltipCfg;
- var tooltip = new Tooltip(tooltipCfg);
- self.tooltip = tooltip; // 需要保持tooltip一直显示
- if (tooltipCfg.alwaysShow && self.prePoint) {
- this.showTooltip(self.prePoint);
- }
- self.bindEvents();
- }
- clear() {
- var tooltip = this.tooltip;
- if (tooltip) {
- tooltip.destroy();
- this.unBindEvents();
- }
- this.tooltip = null;
- this._lastActive = null;
- }
- _getTooltipMarkerStyle() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var {
- type,
- items
- } = cfg;
- var tooltipCfg = this._tooltipCfg;
- if (type === 'rect') {
- var x;
- var y;
- var width;
- var height;
- var chart = this.chart;
- var {
- tl,
- br
- } = chart.get('plotRange');
- var coord = chart.get('coord');
- var firstItem = items[0];
- var lastItem = items[items.length - 1];
- var intervalWidth = firstItem.width;
- if (coord.transposed) {
- x = tl.x;
- y = lastItem.y - intervalWidth * 0.75;
- width = br.x - tl.x;
- height = firstItem.y - lastItem.y + 1.5 * intervalWidth;
- } else {
- x = firstItem.x - intervalWidth * 0.75;
- y = tl.y;
- width = lastItem.x - firstItem.x + 1.5 * intervalWidth;
- height = br.y - tl.y;
- }
- cfg.style = mix({
- x,
- y,
- width,
- height,
- fill: '#CCD6EC',
- opacity: 0.3
- }, tooltipCfg.tooltipMarkerStyle);
- } else {
- cfg.style = mix({
- radius: 4,
- fill: '#fff',
- lineWidth: 2
- }, tooltipCfg.tooltipMarkerStyle);
- }
- return cfg;
- }
- _setTooltip(point, items) {
- var tooltipMarkerCfg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
- this.prePoint = point;
- var lastActive = this._lastActive;
- var tooltip = this.tooltip;
- var cfg = this._tooltipCfg;
- items = _uniqItems(items);
- var chart = this.chart;
- var coord = chart.get('coord');
- var yScale = chart.getYScales()[0];
- var snap = cfg.snap;
- if (snap === false && yScale.isLinear) {
- var invertPoint = coord.invertPoint(point);
- var plot = chart.get('plotRange');
- var tip;
- var pos;
- if (isPointInPlot(point, plot)) {
- if (coord.transposed) {
- tip = yScale.invert(invertPoint.x);
- pos = point.x;
- tooltip.setXTipContent(tip);
- tooltip.setXTipPosition(pos);
- tooltip.setYCrosshairPosition(pos);
- } else {
- tip = yScale.invert(invertPoint.y);
- pos = point.y;
- tooltip.setYTipContent(tip);
- tooltip.setYTipPosition(pos);
- tooltip.setXCrosshairPosition(pos);
- }
- }
- }
- if (cfg.onShow) {
- cfg.onShow({
- x: point.x,
- y: point.y,
- tooltip,
- items,
- tooltipMarkerCfg
- });
- }
- if (isEqual$1(lastActive, items)) {
- if (snap === false && (directionEnabled(cfg.crosshairsType, 'y') || cfg.showYTip)) {
- var canvas = this.chart.get('canvas');
- canvas.draw();
- }
- return;
- }
- this._lastActive = items;
- var onChange = cfg.onChange;
- if (onChange) {
- onChange({
- x: point.x,
- y: point.y,
- tooltip,
- items,
- tooltipMarkerCfg
- });
- }
- var first = items[0];
- var title = first.title || first.name;
- var xTipPosX = first.x;
- if (items.length > 1) {
- xTipPosX = (items[0].x + items[items.length - 1].x) / 2;
- }
- tooltip.setContent(title, items, coord.transposed);
- tooltip.setPosition(items, point);
- if (coord.transposed) {
- var yTipPosY = first.y;
- if (items.length > 1) {
- yTipPosY = (items[0].y + items[items.length - 1].y) / 2;
- }
- tooltip.setYTipContent(title);
- tooltip.setYTipPosition(yTipPosY);
- tooltip.setXCrosshairPosition(yTipPosY);
- if (snap) {
- tooltip.setXTipContent(first.value);
- tooltip.setXTipPosition(xTipPosX);
- tooltip.setYCrosshairPosition(xTipPosX);
- }
- } else {
- tooltip.setXTipContent(title);
- tooltip.setXTipPosition(xTipPosX);
- tooltip.setYCrosshairPosition(xTipPosX);
- if (snap) {
- tooltip.setYTipContent(first.value);
- tooltip.setYTipPosition(first.y);
- tooltip.setXCrosshairPosition(first.y);
- }
- }
- var markerItems = tooltipMarkerCfg.items;
- if (cfg.showTooltipMarker && markerItems.length) {
- tooltipMarkerCfg = this._getTooltipMarkerStyle(tooltipMarkerCfg);
- tooltip.setMarkers(tooltipMarkerCfg);
- } else {
- tooltip.clearMarkers();
- }
- tooltip.show();
- }
- showTooltip(point) {
- var self = this;
- var chart = self.chart;
- var tooltipMarkerType;
- var tooltipMarkerItems = [];
- var items = [];
- var cfg = self._tooltipCfg;
- var {
- showItemMarker,
- itemMarkerStyle,
- alwaysShow
- } = cfg;
- var marker;
- if (showItemMarker) {
- marker = itemMarkerStyle;
- }
- var geoms = chart.get('geoms');
- var coord = chart.get('coord');
- each(geoms, function (geom) {
- if (geom.get('visible')) {
- var type = geom.get('type');
- var records = geom.getSnapRecords(point);
- var adjust = geom.get('adjust'); // 漏斗图和金子塔图tooltip位置有问题,暂时不开放显示
- if (type === 'interval' && adjust && adjust.type === 'symmetric') {
- return;
- }
- each(records, function (record) {
- if (record.x && record.y) {
- var {
- x,
- y,
- _origin,
- color
- } = record;
- var tooltipItem = {
- x,
- y: isArray(y) ? y[1] : y,
- color: color || Global.defaultColor,
- origin: _origin,
- name: getTooltipName(geom, _origin),
- value: getTooltipValue(geom, _origin),
- title: getTooltipTitle(geom, _origin)
- };
- if (marker) {
- tooltipItem.marker = mix({
- fill: color || Global.defaultColor
- }, marker);
- }
- items.push(tooltipItem);
- if (['line', 'area', 'path'].indexOf(type) !== -1) {
- tooltipMarkerType = 'circle';
- tooltipMarkerItems.push(tooltipItem);
- } else if (type === 'interval' && (coord.type === 'cartesian' || coord.type === 'rect')) {
- tooltipMarkerType = 'rect';
- tooltipItem.width = geom.getSize(record._origin);
- tooltipMarkerItems.push(tooltipItem);
- }
- }
- });
- }
- });
- if (items.length) {
- var tooltipMarkerCfg = {
- items: tooltipMarkerItems,
- type: tooltipMarkerType
- };
- self._setTooltip(point, items, tooltipMarkerCfg);
- return;
- }
- if (!alwaysShow) {
- self.hideTooltip();
- }
- }
- hideTooltip() {
- var cfg = this._tooltipCfg;
- this._lastActive = null;
- var tooltip = this.tooltip;
- if (tooltip) {
- tooltip.hide();
- if (cfg.onHide) {
- cfg.onHide({
- tooltip
- });
- }
- var canvas = this.chart.get('canvas');
- canvas.draw();
- }
- }
- _handleEvent(methodName, method, action) {
- var canvas = this.canvas;
- each([].concat(methodName), function (aMethod) {
- if (action === 'bind') {
- canvas.on(aMethod, method);
- } else {
- canvas.off(aMethod, method);
- }
- });
- }
- bindEvents() {
- var cfg = this._tooltipCfg;
- var {
- triggerOn,
- triggerOff,
- alwaysShow
- } = cfg;
- triggerOn && this._handleEvent(triggerOn, this.handleShowEvent, 'bind'); // 如果 !alwaysShow, 则在手势离开后就隐藏
- if (!alwaysShow) {
- this._handleEvent(triggerOff, this.handleHideEvent, 'bind');
- }
- }
- unBindEvents() {
- var cfg = this._tooltipCfg;
- var {
- triggerOn,
- triggerOff,
- alwaysShow
- } = cfg;
- triggerOn && this._handleEvent(triggerOn, this.handleShowEvent, 'unBind');
- if (!alwaysShow) {
- this._handleEvent(triggerOff, this.handleHideEvent, 'unBind');
- }
- }
- }
- function init(chart) {
- var tooltipController = new TooltipController({
- chart
- });
- chart.set('tooltipController', tooltipController);
- chart.tooltip = function (enable, cfg) {
- if (isObject(enable)) {
- cfg = enable;
- enable = true;
- }
- tooltipController.enable = enable;
- if (cfg) {
- tooltipController.cfg = cfg;
- }
- return this;
- };
- }
- function afterGeomDraw(chart) {
- var tooltipController = chart.get('tooltipController');
- tooltipController.render();
- chart.showTooltip = function (point) {
- tooltipController.showTooltip(point);
- return this;
- };
- chart.hideTooltip = function () {
- tooltipController.hideTooltip();
- return this;
- };
- }
- function clearInner(chart) {
- var tooltipController = chart.get('tooltipController');
- tooltipController.clear();
- }
- var tooltip = {
- init,
- afterGeomDraw,
- clearInner
- };
- var Tooltip$1 = /*#__PURE__*/Object.freeze({
- __proto__: null,
- init: init,
- afterGeomDraw: afterGeomDraw,
- clearInner: clearInner,
- 'default': tooltip
- });
- Global.guide = deepMix({
- line: {
- style: {
- stroke: '#a3a3a3',
- lineWidth: 1
- },
- top: true
- },
- text: {
- style: {
- fill: '#787878',
- textAlign: 'center',
- textBaseline: 'middle'
- },
- offsetX: 0,
- offsetY: 0,
- top: true
- },
- rect: {
- style: {
- fill: '#fafafa'
- },
- top: false
- },
- arc: {
- style: {
- stroke: '#a3a3a3'
- },
- top: true
- },
- html: {
- offsetX: 0,
- offsetY: 0,
- alignX: 'center',
- alignY: 'middle'
- },
- tag: {
- top: true,
- offsetX: 0,
- offsetY: 0,
- side: 4,
- background: {
- padding: 5,
- radius: 2,
- fill: '#1890FF'
- },
- textStyle: {
- fontSize: 12,
- fill: '#fff',
- textAlign: 'center',
- textBaseline: 'middle'
- }
- },
- point: {
- top: true,
- offsetX: 0,
- offsetY: 0,
- style: {
- fill: '#fff',
- r: 3,
- lineWidth: 2,
- stroke: '#1890ff'
- }
- }
- }, Global.guide || {});
- class GuideController {
- constructor(cfg) {
- this.guides = [];
- this.xScale = null;
- this.yScales = null;
- this.guideShapes = [];
- mix(this, cfg);
- }
- _toString(position) {
- if (isFunction(position)) {
- position = position(this.xScale, this.yScales);
- }
- position = position.toString();
- return position;
- }
- _getId(shape, guide) {
- var id = guide.id;
- if (!id) {
- var type = guide.type;
- if (type === 'arc' || type === 'line' || type === 'rect') {
- id = this._toString(guide.start) + '-' + this._toString(guide.end);
- } else {
- id = this._toString(guide.position);
- }
- }
- return id;
- }
- paint(coord) {
- var self = this;
- var {
- chart,
- guides,
- xScale,
- yScales
- } = self;
- var guideShapes = [];
- each(guides, function (guide, idx) {
- guide.xScale = xScale;
- guide.yScales = yScales;
- var container;
- if (guide.type === 'regionFilter') {
- // TODO: RegionFilter support animation
- guide.chart = chart;
- } else {
- container = guide.top ? self.frontPlot : self.backPlot;
- }
- guide.coord = coord;
- guide.container = container;
- guide.canvas = chart.get('canvas');
- var shape = guide.render(coord, container);
- if (shape) {
- var id = self._getId(shape, guide);
- [].concat(shape).forEach(function (s) {
- s._id = s.get('className') + '-' + id;
- s.set('index', idx);
- guideShapes.push(s);
- });
- }
- });
- self.guideShapes = guideShapes;
- }
- clear() {
- this.reset();
- this.guides = [];
- return this;
- }
- reset() {
- var guides = this.guides;
- each(guides, function (guide) {
- guide.remove();
- });
- }
- _createGuide(type, cfg) {
- var ClassName = upperFirst(type);
- var guide = new GuideBase[ClassName](deepMix({}, Global.guide[type], cfg));
- this.guides.push(guide);
- return guide;
- }
- line() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('line', cfg);
- }
- text() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('text', cfg);
- }
- arc() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('arc', cfg);
- }
- html() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('html', cfg);
- }
- rect() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('rect', cfg);
- }
- tag() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('tag', cfg);
- }
- point() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('point', cfg);
- }
- regionFilter() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- return this._createGuide('regionFilter', cfg);
- }
- }
- function init$1(chart) {
- var guideController = new GuideController({
- frontPlot: chart.get('frontPlot').addGroup({
- zIndex: 20,
- className: 'guideContainer'
- }),
- backPlot: chart.get('backPlot').addGroup({
- className: 'guideContainer'
- })
- });
- chart.set('guideController', guideController);
- /**
- * 为图表添加 guide
- * @return {GuideController} 返回 guide 控制器
- */
- chart.guide = function () {
- return guideController;
- };
- }
- function afterGeomDraw$1(chart) {
- var guideController = chart.get('guideController');
- if (!guideController.guides.length) {
- return;
- }
- var xScale = chart.getXScale();
- var yScales = chart.getYScales();
- var coord = chart.get('coord');
- guideController.xScale = xScale;
- guideController.yScales = yScales;
- guideController.chart = chart; // for regionFilter
- guideController.paint(coord);
- }
- function clear(chart) {
- chart.get('guideController').clear();
- }
- function repaint(chart) {
- chart.get('guideController').reset();
- }
- var guide = {
- init: init$1,
- afterGeomDraw: afterGeomDraw$1,
- clear,
- repaint
- };
- var Guide = /*#__PURE__*/Object.freeze({
- __proto__: null,
- init: init$1,
- afterGeomDraw: afterGeomDraw$1,
- clear: clear,
- repaint: repaint,
- 'default': guide
- });
- function _defineProperty$3(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- var LEGEND_GAP = 12;
- var MARKER_SIZE = 3;
- var DEFAULT_CFG = {
- itemMarginBottom: 12,
- itemGap: 10,
- showTitle: false,
- titleStyle: {
- fontSize: 12,
- fill: '#808080',
- textAlign: 'start',
- textBaseline: 'top'
- },
- nameStyle: {
- fill: '#808080',
- fontSize: 12,
- textAlign: 'start',
- textBaseline: 'middle'
- },
- valueStyle: {
- fill: '#000000',
- fontSize: 12,
- textAlign: 'start',
- textBaseline: 'middle'
- },
- unCheckStyle: {
- fill: '#bfbfbf'
- },
- itemWidth: 'auto',
- wordSpace: 6,
- selectedMode: 'multiple' // 'multiple' or 'single'
- }; // Register the default configuration for Legend
- Global.legend = deepMix({
- common: DEFAULT_CFG,
- // common legend configuration
- right: mix({
- position: 'right',
- layout: 'vertical'
- }, DEFAULT_CFG),
- left: mix({
- position: 'left',
- layout: 'vertical'
- }, DEFAULT_CFG),
- top: mix({
- position: 'top',
- layout: 'horizontal'
- }, DEFAULT_CFG),
- bottom: mix({
- position: 'bottom',
- layout: 'horizontal'
- }, DEFAULT_CFG)
- }, Global.legend || {});
- function getPaddingByPos(pos, appendPadding) {
- var padding = 0;
- appendPadding = parsePadding(appendPadding);
- switch (pos) {
- case 'top':
- padding = appendPadding[0];
- break;
- case 'right':
- padding = appendPadding[1];
- break;
- case 'bottom':
- padding = appendPadding[2];
- break;
- case 'left':
- padding = appendPadding[3];
- break;
- }
- return padding;
- }
- class LegendController {
- constructor(cfg) {
- var _this = this;
- _defineProperty$3(this, "handleEvent", function (ev) {
- var self = _this;
- function findItem(x, y) {
- var result = null;
- var legends = self.legends;
- each(legends, function (legendItems) {
- each(legendItems, function (legend) {
- var {
- itemsGroup,
- legendHitBoxes
- } = legend;
- var children = itemsGroup.get('children');
- if (children.length) {
- var legendPosX = legend.x;
- var legendPosY = legend.y;
- each(legendHitBoxes, function (box, index) {
- if (x >= box.x + legendPosX && x <= box.x + box.width + legendPosX && y >= box.y + legendPosY && y <= box.height + box.y + legendPosY) {
- // inbox
- result = {
- clickedItem: children[index],
- clickedLegend: legend
- };
- return false;
- }
- });
- }
- });
- });
- return result;
- }
- var chart = self.chart;
- var {
- x,
- y
- } = createEvent(ev, chart);
- var clicked = findItem(x, y);
- if (clicked && clicked.clickedLegend.clickable !== false) {
- var {
- clickedItem,
- clickedLegend
- } = clicked;
- if (clickedLegend.onClick) {
- ev.clickedItem = clickedItem;
- clickedLegend.onClick(ev);
- } else if (!clickedLegend.custom) {
- var checked = clickedItem.get('checked');
- var value = clickedItem.get('dataValue');
- var {
- filteredVals,
- field,
- selectedMode
- } = clickedLegend;
- var isSingeSelected = selectedMode === 'single';
- if (isSingeSelected) {
- chart.filter(field, function (val) {
- return val === value;
- });
- } else {
- if (checked) {
- filteredVals.push(value);
- } else {
- remove$1(filteredVals, value);
- }
- chart.filter(field, function (val) {
- return filteredVals.indexOf(val) === -1;
- });
- }
- chart.repaint();
- }
- }
- });
- this.legendCfg = {};
- this.enable = true;
- this.position = 'top';
- mix(this, cfg);
- var _chart = this.chart;
- this.canvasDom = _chart.get('canvas').get('el');
- this.clear();
- }
- addLegend(scale, items, filteredVals) {
- var self = this;
- var legendCfg = self.legendCfg;
- var field = scale.field;
- var fieldCfg = legendCfg[field];
- if (fieldCfg === false) {
- return null;
- }
- if (fieldCfg && fieldCfg.custom) {
- self.addCustomLegend(field);
- } else {
- var position = legendCfg.position || self.position;
- if (fieldCfg && fieldCfg.position) {
- position = fieldCfg.position;
- }
- if (scale.isCategory) {
- self._addCategoryLegend(scale, items, position, filteredVals);
- }
- }
- }
- addCustomLegend(field) {
- var self = this;
- var legendCfg = self.legendCfg;
- if (field && legendCfg[field]) {
- legendCfg = legendCfg[field];
- }
- var position = legendCfg.position || self.position;
- var legends = self.legends;
- legends[position] = legends[position] || [];
- var items = legendCfg.items;
- if (!items) {
- return null;
- }
- var container = self.container;
- each(items, function (item) {
- if (!isPlainObject(item.marker)) {
- item.marker = {
- symbol: item.marker || 'circle',
- fill: item.fill,
- radius: MARKER_SIZE
- };
- } else {
- item.marker.radius = item.marker.radius || MARKER_SIZE;
- }
- item.checked = isNil(item.checked) ? true : item.checked;
- item.name = item.name || item.value;
- });
- var legend = new List(deepMix({}, Global.legend[position], legendCfg, {
- maxLength: self._getMaxLength(position),
- items,
- parent: container
- }));
- legends[position].push(legend);
- }
- clear() {
- var legends = this.legends;
- each(legends, function (legendItems) {
- each(legendItems, function (legend) {
- legend.clear();
- });
- });
- this.legends = {};
- this.unBindEvents();
- }
- _isFiltered(scale, values, value) {
- var rst = false;
- each(values, function (val) {
- rst = rst || scale.getText(val) === scale.getText(value);
- if (rst) {
- return false;
- }
- });
- return rst;
- }
- _getMaxLength(position) {
- var chart = this.chart;
- var appendPadding = parsePadding(chart.get('appendPadding'));
- return position === 'right' || position === 'left' ? chart.get('height') - (appendPadding[0] + appendPadding[2]) : chart.get('width') - (appendPadding[1] + appendPadding[3]);
- }
- _addCategoryLegend(scale, items, position, filteredVals) {
- var self = this;
- var {
- legendCfg,
- legends,
- container,
- chart
- } = self;
- var field = scale.field;
- legends[position] = legends[position] || [];
- var symbol = 'circle';
- if (legendCfg[field] && legendCfg[field].marker) {
- symbol = legendCfg[field].marker;
- } else if (legendCfg.marker) {
- symbol = legendCfg.marker;
- }
- each(items, function (item) {
- if (isPlainObject(symbol)) {
- mix(item.marker, symbol);
- } else {
- item.marker.symbol = symbol;
- }
- if (filteredVals) {
- item.checked = !self._isFiltered(scale, filteredVals, item.dataValue);
- }
- });
- var legendItems = chart.get('legendItems');
- legendItems[field] = items;
- var lastCfg = deepMix({}, Global.legend[position], legendCfg[field] || legendCfg, {
- maxLength: self._getMaxLength(position),
- items,
- field,
- filteredVals,
- parent: container
- });
- if (lastCfg.showTitle) {
- deepMix(lastCfg, {
- title: scale.alias || scale.field
- });
- }
- var legend = new List(lastCfg);
- legends[position].push(legend);
- return legend;
- }
- _alignLegend(legend, pre, position) {
- var self = this;
- var {
- tl,
- bl
- } = self.plotRange;
- var chart = self.chart;
- var offsetX = legend.offsetX || 0;
- var offsetY = legend.offsetY || 0;
- var chartWidth = chart.get('width');
- var chartHeight = chart.get('height');
- var appendPadding = parsePadding(chart.get('appendPadding'));
- var legendHeight = legend.getHeight();
- var legendWidth = legend.getWidth();
- var x = 0;
- var y = 0;
- if (position === 'left' || position === 'right') {
- var verticalAlign = legend.verticalAlign || 'middle';
- var height = Math.abs(tl.y - bl.y);
- x = position === 'left' ? appendPadding[3] : chartWidth - legendWidth - appendPadding[1];
- y = (height - legendHeight) / 2 + tl.y;
- if (verticalAlign === 'top') {
- y = tl.y;
- } else if (verticalAlign === 'bottom') {
- y = bl.y - legendHeight;
- }
- if (pre) {
- y = pre.get('y') - legendHeight - LEGEND_GAP;
- }
- } else {
- var align = legend.align || 'left';
- x = appendPadding[3];
- if (align === 'center') {
- x = chartWidth / 2 - legendWidth / 2;
- } else if (align === 'right') {
- x = chartWidth - (legendWidth + appendPadding[1]);
- }
- y = position === 'top' ? appendPadding[0] + Math.abs(legend.container.getBBox().minY) : chartHeight - legendHeight;
- if (pre) {
- var preWidth = pre.getWidth();
- x = pre.x + preWidth + LEGEND_GAP;
- }
- }
- if (position === 'bottom' && offsetY > 0) {
- offsetY = 0;
- }
- if (position === 'right' && offsetX > 0) {
- offsetX = 0;
- }
- legend.moveTo(x + offsetX, y + offsetY);
- }
- alignLegends() {
- var self = this;
- var legends = self.legends;
- each(legends, function (legendItems, position) {
- each(legendItems, function (legend, index) {
- var pre = legendItems[index - 1];
- self._alignLegend(legend, pre, position);
- });
- });
- return self;
- }
- bindEvents() {
- var legendCfg = this.legendCfg;
- var triggerOn = legendCfg.triggerOn || 'touchstart';
- addEventListener(this.canvasDom, triggerOn, this.handleEvent);
- }
- unBindEvents() {
- var legendCfg = this.legendCfg;
- var triggerOn = legendCfg.triggerOn || 'touchstart';
- removeEventListener(this.canvasDom, triggerOn, this.handleEvent);
- }
- }
- function init$2(chart) {
- var legendController = new LegendController({
- container: chart.get('backPlot'),
- plotRange: chart.get('plotRange'),
- chart
- });
- chart.set('legendController', legendController);
- chart.legend = function (field, cfg) {
- var legendCfg = legendController.legendCfg;
- legendController.enable = true;
- if (isBoolean(field)) {
- legendController.enable = field;
- legendCfg = cfg || {};
- } else if (isObject(field)) {
- legendCfg = field;
- } else {
- legendCfg[field] = cfg;
- }
- legendController.legendCfg = legendCfg;
- return this;
- };
- }
- function beforeGeomDraw(chart) {
- var legendController = chart.get('legendController');
- if (!legendController.enable) return null; // legend is not displayed
- var legendCfg = legendController.legendCfg;
- if (legendCfg && legendCfg.custom) {
- legendController.addCustomLegend();
- } else {
- var legendItems = chart.getLegendItems();
- var scales = chart.get('scales');
- var filters = chart.get('filters');
- each(legendItems, function (items, field) {
- var scale = scales[field];
- var values = scale.values;
- var filteredVals;
- if (filters && filters[field]) {
- filteredVals = values.filter(function (v) {
- return !filters[field](v);
- });
- } else {
- filteredVals = [];
- }
- legendController.addLegend(scale, items, filteredVals);
- });
- }
- if (legendCfg && legendCfg.clickable !== false) {
- legendController.bindEvents();
- }
- var legends = legendController.legends;
- var legendRange = {
- top: 0,
- right: 0,
- bottom: 0,
- left: 0
- };
- each(legends, function (legendItems, position) {
- var padding = 0;
- each(legendItems, function (legend) {
- var width = legend.getWidth();
- var height = legend.getHeight();
- if (position === 'top' || position === 'bottom') {
- padding = Math.max(padding, height);
- if (legend.offsetY > 0) {
- padding += legend.offsetY;
- }
- } else {
- padding = Math.max(padding, width);
- if (legend.offsetX > 0) {
- padding += legend.offsetX;
- }
- }
- });
- legendRange[position] = padding + getPaddingByPos(position, chart.get('appendPadding'));
- });
- chart.set('legendRange', legendRange);
- }
- function afterGeomDraw$2(chart) {
- var legendController = chart.get('legendController');
- legendController.alignLegends();
- }
- function clearInner$1(chart) {
- var legendController = chart.get('legendController');
- legendController.clear();
- chart.set('legendRange', null);
- }
- var legend = {
- init: init$2,
- beforeGeomDraw,
- afterGeomDraw: afterGeomDraw$2,
- clearInner: clearInner$1
- };
- var Legend = /*#__PURE__*/Object.freeze({
- __proto__: null,
- init: init$2,
- beforeGeomDraw: beforeGeomDraw,
- afterGeomDraw: afterGeomDraw$2,
- clearInner: clearInner$1,
- 'default': legend
- });
- var clock = typeof performance === 'object' && performance.now ? performance : Date;
- class Timeline {
- constructor() {
- this.anims = [];
- this.time = null;
- this.playing = false;
- this.canvas = [];
- }
- play() {
- var self = this;
- self.time = clock.now();
- self.playing = true;
- function step() {
- if (self.playing) {
- requestAnimationFrame$1(step);
- self.update();
- }
- }
- requestAnimationFrame$1(step);
- }
- stop() {
- this.playing = false;
- this.time = null;
- this.canvas = [];
- }
- pushAnim(animInfo) {
- this.anims.push(animInfo);
- if (this.playing) {
- return;
- }
- this.play();
- }
- update() {
- var currentTime = clock.now();
- this.canvas = [];
- if (!this.anims.length) {
- this.stop();
- return;
- }
- for (var i = 0; i < this.anims.length; i++) {
- var propertyAnim = this.anims[i];
- if (currentTime < propertyAnim.startTime || propertyAnim.hasEnded) {
- continue;
- }
- var shape = propertyAnim.shape; // shape
- if (shape.get('destroyed')) {
- this.anims.splice(i, 1);
- i--;
- continue;
- }
- var {
- startState,
- endState,
- interpolate,
- duration
- } = propertyAnim;
- if (currentTime >= propertyAnim.startTime && !propertyAnim.hasStarted) {
- propertyAnim.hasStarted = true;
- if (propertyAnim.onStart) {
- propertyAnim.onStart();
- }
- }
- var t = (currentTime - propertyAnim.startTime) / duration;
- t = Math.max(0, Math.min(t, 1));
- t = propertyAnim.easing(t);
- if (propertyAnim.onFrame) {
- propertyAnim.onFrame(t);
- } else {
- for (var key in interpolate) {
- var diff = interpolate[key];
- var value = diff(t);
- var newValue = void 0;
- if (key === 'points') {
- newValue = [];
- var aLen = Math.max(startState.points.length, endState.points.length);
- for (var j = 0; j < aLen; j += 2) {
- newValue.push({
- x: value[j],
- y: value[j + 1]
- });
- }
- } else {
- newValue = value;
- }
- shape._attrs.attrs[key] = newValue;
- shape._attrs.bbox = null; // should clear calculated bbox
- }
- }
- var canvas = shape.get('canvas');
- if (this.canvas.indexOf(canvas) === -1) {
- this.canvas.push(canvas);
- }
- if (propertyAnim.onUpdate) {
- propertyAnim.onUpdate(t);
- }
- if (currentTime >= propertyAnim.endTime && !propertyAnim.hasEnded) {
- propertyAnim.hasEnded = true;
- if (propertyAnim.onEnd) {
- propertyAnim.onEnd();
- }
- }
- if (t === 1) {
- // end
- this.anims.splice(i, 1);
- i--;
- }
- }
- this.canvas.map(function (c) {
- c.draw();
- return c;
- });
- this.time = clock.now();
- }
- }
- function linear$1(k) {
- return k;
- }
- function quadraticIn(k) {
- return k * k;
- }
- function quadraticOut(k) {
- return k * (2 - k);
- }
- function quadraticInOut(k) {
- if ((k *= 2) < 1) {
- return 0.5 * k * k;
- }
- return -0.5 * (--k * (k - 2) - 1);
- }
- function cubicIn(k) {
- return k * k * k;
- }
- function cubicOut(k) {
- return --k * k * k + 1;
- }
- function cubicInOut(k) {
- if ((k *= 2) < 1) {
- return 0.5 * k * k * k;
- }
- return 0.5 * ((k -= 2) * k * k + 2);
- }
- function elasticIn(k) {
- var s;
- var a = 0.1;
- var p = 0.4;
- if (k === 0) return 0;
- if (k === 1) return 1;
- if (!a || a < 1) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- return -(a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p));
- }
- function elasticOut(k) {
- var s;
- var a = 0.1;
- var p = 0.4;
- if (k === 0) return 0;
- if (k === 1) return 1;
- if (!a || a < 1) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- return a * Math.pow(2, -10 * k) * Math.sin((k - s) * (2 * Math.PI) / p) + 1;
- }
- function elasticInOut(k) {
- var s;
- var a = 0.1;
- var p = 0.4;
- if (k === 0) return 0;
- if (k === 1) return 1;
- if (!a || a < 1) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- if ((k *= 2) < 1) {
- return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p));
- }
- return a * Math.pow(2, -10 * (k -= 1)) * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1;
- }
- function backIn(k) {
- var s = 1.70158;
- return k * k * ((s + 1) * k - s);
- }
- function backOut(k) {
- var s = 1.70158;
- return (k = k - 1) * k * ((s + 1) * k + s) + 1;
- }
- function backInOut(k) {
- var s = 1.70158 * 1.525;
- if ((k *= 2) < 1) {
- return 0.5 * (k * k * ((s + 1) * k - s));
- }
- return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2);
- }
- function bounceIn(k) {
- return 1 - bounceOut(1 - k);
- }
- function bounceOut(k) {
- if ((k /= 1) < 1 / 2.75) {
- return 7.5625 * k * k;
- } else if (k < 2 / 2.75) {
- return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75;
- } else if (k < 2.5 / 2.75) {
- return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375;
- }
- return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375;
- }
- function bounceInOut(k) {
- if (k < 0.5) {
- return bounceIn(k * 2) * 0.5;
- }
- return bounceOut(k * 2 - 1) * 0.5 + 0.5;
- }
- var Easing = /*#__PURE__*/Object.freeze({
- __proto__: null,
- linear: linear$1,
- quadraticIn: quadraticIn,
- quadraticOut: quadraticOut,
- quadraticInOut: quadraticInOut,
- cubicIn: cubicIn,
- cubicOut: cubicOut,
- cubicInOut: cubicInOut,
- elasticIn: elasticIn,
- elasticOut: elasticOut,
- elasticInOut: elasticInOut,
- backIn: backIn,
- backOut: backOut,
- backInOut: backInOut,
- bounceIn: bounceIn,
- bounceOut: bounceOut,
- bounceInOut: bounceInOut
- });
- function plainArray(arr) {
- var result = [];
- for (var i = 0, len = arr.length; i < len; i++) {
- if (arr[i]) {
- result.push(arr[i].x);
- result.push(arr[i].y);
- }
- }
- return result;
- }
- function interpolateNumber(a, b) {
- a = +a;
- b -= a;
- return function (t) {
- return a + b * t;
- };
- }
- function interpolateArray(a, b) {
- var nb = b ? b.length : 0;
- var na = a ? Math.min(nb, a.length) : 0;
- var x = new Array(na);
- var c = new Array(nb);
- var i;
- for (i = 0; i < na; ++i) {
- x[i] = interpolateNumber(a[i], b[i]);
- }
- for (; i < nb; ++i) {
- c[i] = b[i];
- }
- return function (t) {
- for (i = 0; i < na; ++i) {
- c[i] = x[i](t);
- }
- return c;
- };
- }
- class Animator {
- constructor(shape, source, timeline) {
- this.hasStarted = false;
- this.hasEnded = false;
- this.shape = shape;
- this.source = source;
- this.timeline = timeline;
- this.animate = null;
- } // delay, attrs, duration, easing
- to() {
- var cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var delay = cfg.delay || 0;
- var attrs = cfg.attrs || {};
- var duration = cfg.duration || 1000;
- var easing; // 缓动函数
- if (typeof cfg.easing === 'function') {
- easing = cfg.easing;
- } else {
- easing = Easing[cfg.easing] || linear$1;
- }
- var animInfo = {
- shape: this.shape,
- startTime: this.timeline.time + delay,
- duration,
- easing
- };
- var interpolate = {}; // 差值函数
- for (var attrName in attrs) {
- var startValue = this.source[attrName];
- var endValue = attrs[attrName];
- if (attrName === 'points') {
- startValue = plainArray(startValue);
- endValue = plainArray(endValue);
- interpolate.points = interpolateArray(startValue, endValue);
- this.source.points = startValue;
- attrs.points = endValue;
- } else if (attrName === 'matrix') {
- interpolate.matrix = interpolateArray(startValue, endValue);
- } else {
- interpolate[attrName] = interpolateNumber(startValue, endValue);
- }
- }
- animInfo.interpolate = interpolate;
- animInfo.startState = this.source;
- animInfo.endState = attrs;
- animInfo.endTime = animInfo.startTime + duration;
- this.timeline.pushAnim(animInfo);
- this.animate = animInfo;
- return this;
- }
- onFrame(callback) {
- // 自定义每一帧动画的动作
- if (this.animate) {
- this.animate.onFrame = function (frame) {
- callback(frame);
- };
- }
- return this;
- }
- onStart(callback) {
- if (this.animate) {
- this.animate.onStart = function () {
- callback();
- };
- }
- return this;
- }
- onUpdate(callback) {
- if (this.animate) {
- this.animate.onUpdate = function (frame) {
- callback(frame);
- };
- }
- return this;
- }
- onEnd(callback) {
- if (this.animate) {
- this.animate.onEnd = function () {
- callback();
- };
- }
- return this;
- }
- }
- function ownKeys$1(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
- function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$1(Object(source), true).forEach(function (key) { _defineProperty$4(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$1(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
- function _defineProperty$4(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- var defaultAnimationCfg = {
- appear: {
- duration: 450,
- easing: 'quadraticOut'
- },
- // 'appear' animation options
- update: {
- duration: 300,
- easing: 'quadraticOut'
- },
- // 'update' animation options
- enter: {
- duration: 300,
- easing: 'quadraticOut'
- },
- // 'enter' animation options
- leave: {
- duration: 350,
- easing: 'quadraticIn'
- } // 'leave' animation options
- };
- var Animate = {
- defaultCfg: {},
- Action: {},
- getAnimation(geomType, coord, animationType) {
- var geomAnimateCfg = this.defaultCfg[geomType];
- if (geomAnimateCfg) {
- var animation = geomAnimateCfg[animationType];
- if (isFunction(animation)) {
- return animation(coord);
- }
- }
- return false;
- },
- getAnimateCfg(geomType, animationType) {
- var defaultCfg = defaultAnimationCfg[animationType];
- var geomConfig = this.defaultCfg[geomType];
- if (geomConfig && geomConfig.cfg && geomConfig.cfg[animationType]) {
- return deepMix({}, defaultCfg, geomConfig.cfg[animationType]);
- }
- return defaultCfg;
- },
- registerAnimation(animationName, animationFun) {
- if (!this.Action) {
- this.Action = {};
- }
- this.Action = _objectSpread$1(_objectSpread$1({}, this.Action), {}, {
- [animationName]: animationFun
- });
- }
- };
- /**
- * Utility
- * @author sima.zhang1990@gmail.com
- */
- function getCoordInfo(coord) {
- var start = coord.start;
- var end = coord.end;
- return {
- start,
- end,
- width: end.x - start.x,
- height: Math.abs(end.y - start.y)
- };
- }
- function getScaledMatrix(shape, v, direct) {
- var scaledMatrix;
- shape.apply(v);
- var x = v[0];
- var y = v[1];
- if (direct === 'x') {
- shape.transform([['t', x, y], ['s', 0.01, 1], ['t', -x, -y]]);
- var matrix = shape.getMatrix();
- scaledMatrix = Matrix.transform(matrix, [['t', x, y], ['s', 100, 1], ['t', -x, -y]]);
- } else if (direct === 'y') {
- shape.transform([['t', x, y], ['s', 1, 0.01], ['t', -x, -y]]);
- var _matrix = shape.getMatrix();
- scaledMatrix = Matrix.transform(_matrix, [['t', x, y], ['s', 1, 100], ['t', -x, -y]]);
- } else if (direct === 'xy') {
- shape.transform([['t', x, y], ['s', 0.01, 0.01], ['t', -x, -y]]);
- var _matrix2 = shape.getMatrix();
- scaledMatrix = Matrix.transform(_matrix2, [['t', x, y], ['s', 100, 100], ['t', -x, -y]]);
- }
- return scaledMatrix;
- }
- function getAnimateParam(animateCfg, index, id) {
- var result = {};
- if (animateCfg.delay) {
- result.delay = isFunction(animateCfg.delay) ? animateCfg.delay(index, id) : animateCfg.delay;
- }
- result.easing = animateCfg.easing;
- result.duration = animateCfg.duration;
- result.delay = animateCfg.delay;
- return result;
- }
- function doAnimation(shape, endState, animateCfg, callback) {
- var id = shape._id;
- var index = shape.get('index');
- var {
- easing,
- delay,
- duration
- } = getAnimateParam(animateCfg, index, id);
- var anim = shape.animate().to({
- attrs: endState,
- duration,
- delay,
- easing
- });
- if (callback) {
- anim.onEnd(function () {
- callback();
- });
- }
- }
- /**
- * Animation functions for shape
- * @author sima.zhang1990@gmail.com
- */
- /*
- function waveIn(shape, animateCfg, coord) {
- const clip = Helpers.getClip(coord);
- clip.set('canvas', shape.get('canvas'));
- shape.attr('clip', clip);
- const onEnd = function() {
- shape.attr('clip', null);
- clip.remove(true);
- };
- Helpers.doAnimation(clip, clip.endState, animateCfg, onEnd);
- }
- function scaleInX(shape, animateCfg) {
- const box = shape.getBBox();
- const points = shape.get('origin').points;
- let x;
- const y = (box.minY + box.maxY) / 2;
- if (points[0].y - points[1].y > 0) { // 当顶点在零点之下
- x = box.maxX;
- } else {
- x = box.minX;
- }
- const scaledMatrix = Helpers.getScaledMatrix(shape, [ x, y ], 'x');
- Helpers.doAnimation(shape, { matrix: scaledMatrix }, animateCfg);
- }
- function scaleInY(shape, animateCfg) {
- const box = shape.getBBox();
- const points = shape.get('origin').points;
- const x = (box.minX + box.maxX) / 2;
- let y;
- if (points[0].y - points[1].y <= 0) { // 当顶点在零点之下
- y = box.maxY;
- } else {
- y = box.minY;
- }
- const scaledMatrix = Helpers.getScaledMatrix(shape, [ x, y ], 'x');
- Helpers.doAnimation(shape, { matrix: scaledMatrix }, animateCfg);
- }
- */
- function fadeIn(shape, animateCfg) {
- var fillOpacity = isNil(shape.attr('fillOpacity')) ? 1 : shape.attr('fillOpacity');
- var strokeOpacity = isNil(shape.attr('strokeOpacity')) ? 1 : shape.attr('strokeOpacity');
- shape.attr('fillOpacity', 0);
- shape.attr('strokeOpacity', 0);
- var endState = {
- fillOpacity,
- strokeOpacity
- };
- doAnimation(shape, endState, animateCfg);
- }
- var ShapeAction = /*#__PURE__*/Object.freeze({
- __proto__: null,
- fadeIn: fadeIn
- });
- /**
- * Group animate functions
- * @author sima.zhang1990@gmail.com
- */
- function _groupScaleIn(container, animateCfg, coord, zeroY, type) {
- var {
- start,
- end,
- width,
- height
- } = getCoordInfo(coord);
- var x;
- var y;
- var clip = new Shape$2.Rect({
- attrs: {
- x: start.x,
- y: end.y,
- width,
- height
- }
- });
- if (type === 'y') {
- x = start.x + width / 2;
- y = zeroY.y < start.y ? zeroY.y : start.y;
- } else if (type === 'x') {
- x = zeroY.x > start.x ? zeroY.x : start.x;
- y = start.y + height / 2;
- } else if (type === 'xy') {
- if (coord.isPolar) {
- x = coord.center.x;
- y = coord.center.y;
- } else {
- x = (start.x + end.x) / 2;
- y = (start.y + end.y) / 2;
- }
- }
- var endMatrix = getScaledMatrix(clip, [x, y], type);
- clip.isClip = true;
- clip.endState = {
- matrix: endMatrix
- };
- clip.set('canvas', container.get('canvas'));
- container.attr('clip', clip);
- var onEnd = function onEnd() {
- container.attr('clip', null);
- clip.remove(true);
- };
- doAnimation(clip, clip.endState, animateCfg, onEnd);
- }
- function _shapeScale(container, animateCfg, type) {
- var shapes = container.get('children');
- var x;
- var y;
- var endMatrix;
- for (var i = 0, len = shapes.length; i < len; i++) {
- var shape = shapes[i];
- var box = shape.getBBox();
- x = (box.minX + box.maxX) / 2;
- y = (box.minY + box.maxY) / 2;
- endMatrix = getScaledMatrix(shape, [x, y], type);
- doAnimation(shape, {
- matrix: endMatrix
- }, animateCfg);
- }
- }
- function groupScaleInX(container, animateCfg, coord, zeroY) {
- _groupScaleIn(container, animateCfg, coord, zeroY, 'x');
- }
- function groupScaleInY(container, animateCfg, coord, zeroY) {
- _groupScaleIn(container, animateCfg, coord, zeroY, 'y');
- }
- function groupScaleInXY(container, animateCfg, coord, zeroY) {
- _groupScaleIn(container, animateCfg, coord, zeroY, 'xy');
- }
- function shapesScaleInX(container, animateCfg) {
- _shapeScale(container, animateCfg, 'x');
- }
- function shapesScaleInY(container, animateCfg) {
- _shapeScale(container, animateCfg, 'y');
- }
- function shapesScaleInXY(container, animateCfg) {
- _shapeScale(container, animateCfg, 'xy');
- }
- function groupWaveIn(container, animateCfg, coord) {
- var clip = getClip(coord);
- clip.set('canvas', container.get('canvas'));
- container.attr('clip', clip);
- var onEnd = function onEnd() {
- container.attr('clip', null);
- clip.remove(true);
- };
- var endState = {};
- if (coord.isPolar) {
- var {
- startAngle,
- endAngle
- } = coord;
- endState.endAngle = endAngle;
- clip.attr('endAngle', startAngle);
- } else {
- var {
- start,
- end
- } = coord;
- var width = Math.abs(start.x - end.x);
- var height = Math.abs(start.y - end.y);
- if (coord.isTransposed) {
- clip.attr('height', 0);
- endState.height = height;
- } else {
- clip.attr('width', 0);
- endState.width = width;
- }
- }
- doAnimation(clip, endState, animateCfg, onEnd);
- }
- var GroupAction = /*#__PURE__*/Object.freeze({
- __proto__: null,
- groupWaveIn: groupWaveIn,
- groupScaleInX: groupScaleInX,
- groupScaleInY: groupScaleInY,
- groupScaleInXY: groupScaleInXY,
- shapesScaleInX: shapesScaleInX,
- shapesScaleInY: shapesScaleInY,
- shapesScaleInXY: shapesScaleInXY
- });
- /**
- * Handle the detail animations
- * @author sima.zhang1990@gmail.com
- */
- var timeline;
- Element$1.prototype.animate = function () {
- var attrs = mix({}, this.get('attrs'));
- return new Animator(this, attrs, timeline);
- };
- Chart.prototype.animate = function (cfg) {
- this.set('animate', cfg);
- return this;
- };
- Animate.Action = ShapeAction;
- Animate.defaultCfg = {
- interval: {
- enter(coord) {
- if (coord.isPolar && coord.transposed) {
- // for pie chart
- return function (shape) {
- shape.set('zIndex', -1);
- var container = shape.get('parent');
- container.sort();
- };
- }
- return fadeIn;
- }
- },
- area: {
- enter(coord) {
- if (coord.isPolar) return null;
- return fadeIn;
- }
- },
- line: {
- enter(coord) {
- if (coord.isPolar) return null;
- return fadeIn;
- }
- },
- path: {
- enter(coord) {
- if (coord.isPolar) return null;
- return fadeIn;
- }
- }
- };
- var GROUP_ANIMATION = {
- line(coord) {
- if (coord.isPolar) {
- return groupScaleInXY;
- }
- return groupWaveIn;
- },
- area(coord) {
- if (coord.isPolar) {
- return groupScaleInXY;
- }
- return groupWaveIn;
- },
- path(coord) {
- if (coord.isPolar) {
- return groupScaleInXY;
- }
- return groupWaveIn;
- },
- point() {
- return shapesScaleInXY;
- },
- interval(coord) {
- var result;
- if (coord.isPolar) {
- // polar coodinate
- result = groupScaleInXY;
- if (coord.transposed) {
- // pie chart
- result = groupWaveIn;
- }
- } else {
- result = coord.transposed ? groupScaleInX : groupScaleInY;
- }
- return result;
- },
- schema() {
- return groupWaveIn;
- }
- };
- function diff(fromAttrs, toAttrs) {
- var endState = {};
- for (var k in toAttrs) {
- if (isNumber(fromAttrs[k]) && fromAttrs[k] !== toAttrs[k]) {
- endState[k] = toAttrs[k];
- } else if (isArray(fromAttrs[k]) && JSON.stringify(fromAttrs[k]) !== JSON.stringify(toAttrs[k])) {
- endState[k] = toAttrs[k];
- }
- }
- return endState;
- } // Add a unique id identifier to each shape
- function _getShapeId(geom, dataObj, geomIdx) {
- var type = geom.get('type');
- var id = 'geom' + geomIdx + '-' + type;
- var xScale = geom.getXScale();
- var yScale = geom.getYScale();
- var xField = xScale.field || 'x';
- var yField = yScale.field || 'y';
- var yVal = dataObj[yField];
- var xVal;
- if (xScale.isIdentity) {
- xVal = xScale.value;
- } else {
- xVal = dataObj[xField];
- }
- if (type === 'interval' || type === 'schema') {
- id += '-' + xVal;
- } else if (type === 'line' || type === 'area' || type === 'path') {
- id += '-' + type;
- } else {
- id += xScale.isCategory ? '-' + xVal : '-' + xVal + '-' + yVal;
- }
- var groupScales = geom._getGroupScales();
- each(groupScales, function (groupScale) {
- var field = groupScale.field;
- if (groupScale.type !== 'identity') {
- id += '-' + dataObj[field];
- }
- });
- return id;
- } // get geometry's shapes
- function getShapes(geoms, chart, coord) {
- var shapes = [];
- each(geoms, function (geom, geomIdx) {
- var geomContainer = geom.get('container');
- var geomShapes = geomContainer.get('children');
- var type = geom.get('type');
- var animateCfg = isNil(geom.get('animateCfg')) ? _getAnimateCfgByShapeType(type, chart) : geom.get('animateCfg');
- if (animateCfg !== false) {
- each(geomShapes, function (shape, index) {
- if (shape.get('className') === type) {
- shape._id = _getShapeId(geom, shape.get('origin')._origin, geomIdx);
- shape.set('coord', coord);
- shape.set('animateCfg', animateCfg);
- shape.set('index', index);
- shapes.push(shape);
- }
- });
- }
- geom.set('shapes', geomShapes);
- });
- return shapes;
- }
- function cache(shapes) {
- var rst = {};
- for (var i = 0, len = shapes.length; i < len; i++) {
- var shape = shapes[i];
- if (!shape._id || shape.isClip) continue;
- var id = shape._id;
- rst[id] = {
- _id: id,
- type: shape.get('type'),
- // the type of shape
- attrs: mix({}, shape._attrs.attrs),
- // the graphics attributes of shape
- className: shape.get('className'),
- geomType: shape.get('className'),
- index: shape.get('index'),
- coord: shape.get('coord'),
- animateCfg: shape.get('animateCfg')
- };
- }
- return rst;
- }
- function getAnimate(geomType, coord, animationType, animationName) {
- var result;
- if (isFunction(animationName)) {
- result = animationName;
- } else if (isString(animationName)) {
- result = Animate.Action[animationName];
- } else {
- result = Animate.getAnimation(geomType, coord, animationType);
- }
- return result;
- }
- function getAnimateCfg(geomType, animationType, animateCfg) {
- if (animateCfg === false || isObject(animateCfg) && animateCfg[animationType] === false) {
- return false;
- }
- var defaultCfg = Animate.getAnimateCfg(geomType, animationType);
- if (animateCfg && animateCfg[animationType]) {
- return deepMix({}, defaultCfg, animateCfg[animationType]);
- }
- return defaultCfg;
- }
- function addAnimate(cache, shapes, canvas) {
- var animate;
- var animateCfg; // the order of animation: leave -> update -> enter
- var updateShapes = [];
- var newShapes = [];
- each(shapes, function (shape) {
- var result = cache[shape._id];
- if (!result) {
- newShapes.push(shape);
- } else {
- shape.set('cacheShape', result);
- updateShapes.push(shape);
- delete cache[shape._id];
- }
- }); // first do the leave animation
- each(cache, function (deletedShape) {
- var {
- className,
- coord,
- _id,
- attrs,
- index,
- type
- } = deletedShape;
- animateCfg = getAnimateCfg(className, 'leave', deletedShape.animateCfg);
- if (animateCfg === false) return true;
- animate = getAnimate(className, coord, 'leave', animateCfg.animation);
- if (isFunction(animate)) {
- var tempShape = canvas.addShape(type, {
- attrs,
- index,
- canvas,
- className
- });
- tempShape._id = _id;
- animate(tempShape, animateCfg, coord);
- }
- }); // then do the update animation
- each(updateShapes, function (updateShape) {
- var className = updateShape.get('className');
- animateCfg = getAnimateCfg(className, 'update', updateShape.get('animateCfg'));
- if (animateCfg === false) return true;
- var coord = updateShape.get('coord');
- var cacheAttrs = updateShape.get('cacheShape').attrs;
- var endState = diff(cacheAttrs, updateShape._attrs.attrs); // 判断如果属性相同的话就不进行变换
- if (Object.keys(endState).length) {
- animate = getAnimate(className, coord, 'update', animateCfg.animation);
- if (isFunction(animate)) {
- animate(updateShape, animateCfg, coord);
- } else {
- updateShape.attr(cacheAttrs);
- updateShape.animate().to({
- attrs: endState,
- duration: animateCfg.duration,
- easing: animateCfg.easing,
- delay: animateCfg.delay
- }).onEnd(function () {
- updateShape.set('cacheShape', null);
- });
- }
- }
- }); // last, enter animation
- each(newShapes, function (newShape) {
- // 新图形元素的进场元素
- var className = newShape.get('className');
- var coord = newShape.get('coord');
- animateCfg = getAnimateCfg(className, 'enter', newShape.get('animateCfg'));
- if (animateCfg === false) return true;
- animate = getAnimate(className, coord, 'enter', animateCfg.animation);
- if (isFunction(animate)) {
- if (className === 'interval' && coord.isPolar && coord.transposed) {
- var index = newShape.get('index');
- var lastShape = updateShapes[index - 1];
- animate(newShape, animateCfg, lastShape);
- } else {
- animate(newShape, animateCfg, coord);
- }
- }
- });
- }
- function _getAnimateCfgByShapeType(type, chart) {
- if (!type) {
- return null;
- }
- var animateCfg = chart.get('animate');
- if (type.indexOf('guide-tag') > -1) {
- type = 'guide-tag';
- }
- if (isObject(animateCfg)) {
- return animateCfg[type];
- }
- if (animateCfg === false) {
- return false;
- }
- return null;
- }
- function afterCanvasInit()
- /* chart */
- {
- timeline = new Timeline();
- timeline.play();
- }
- function beforeCanvasDraw(chart) {
- if (chart.get('animate') === false) {
- return;
- }
- var isUpdate = chart.get('isUpdate');
- var canvas = chart.get('canvas');
- var coord = chart.get('coord');
- var geoms = chart.get('geoms');
- var caches = canvas.get('caches') || [];
- if (caches.length === 0) {
- isUpdate = false;
- }
- var cacheShapes = getShapes(geoms, chart, coord);
- var {
- frontPlot,
- backPlot
- } = chart.get('axisController');
- var axisShapes = frontPlot.get('children').concat(backPlot.get('children'));
- var guideShapes = [];
- if (chart.get('guideController')) {
- guideShapes = chart.get('guideController').guideShapes;
- }
- var componentShapes = [];
- axisShapes.concat(guideShapes).forEach(function (s) {
- var className = s.get('className');
- var animateCfg = _getAnimateCfgByShapeType(className, chart);
- s.set('coord', coord);
- s.set('animateCfg', animateCfg);
- componentShapes.push(s);
- cacheShapes.push(s);
- });
- canvas.set('caches', cache(cacheShapes));
- if (isUpdate) {
- addAnimate(caches, cacheShapes, canvas);
- } else {
- // do the appear animation
- var animateCfg;
- var animate;
- each(geoms, function (geom) {
- var type = geom.get('type');
- var geomCfg = isNil(geom.get('animateCfg')) ? _getAnimateCfgByShapeType(type, chart) : geom.get('animateCfg');
- if (geomCfg !== false) {
- animateCfg = getAnimateCfg(type, 'appear', geomCfg);
- animate = getAnimate(type, coord, 'appear', animateCfg.animation);
- if (isFunction(animate)) {
- var shapes = geom.get('shapes');
- each(shapes, function (shape) {
- animate(shape, animateCfg, coord);
- });
- } else if (GROUP_ANIMATION[type]) {
- // do the default animation
- animate = GroupAction[animateCfg.animation] || GROUP_ANIMATION[type](coord);
- var yScale = geom.getYScale();
- var zeroY = coord.convertPoint({
- x: 0,
- y: yScale.scale(geom.getYMinValue())
- });
- var container = geom.get('container');
- animate && animate(container, animateCfg, coord, zeroY);
- }
- }
- }); // do the animation of components
- each(componentShapes, function (shape) {
- var animateCfg = shape.get('animateCfg');
- var className = shape.get('className');
- if (animateCfg && animateCfg.appear) {
- // if user configure
- var defaultCfg = Animate.getAnimateCfg(className, 'appear');
- var appearCfg = deepMix({}, defaultCfg, animateCfg.appear);
- var _animate = getAnimate(className, coord, 'appear', appearCfg.animation);
- if (isFunction(_animate)) {
- _animate(shape, appearCfg, coord);
- }
- }
- });
- }
- }
- function afterCanvasDestroyed()
- /* chart */
- {
- timeline.stop();
- }
- var detail = {
- afterCanvasInit,
- beforeCanvasDraw,
- afterCanvasDestroyed
- };
- var Animation = /*#__PURE__*/Object.freeze({
- __proto__: null,
- afterCanvasInit: afterCanvasInit,
- beforeCanvasDraw: beforeCanvasDraw,
- afterCanvasDestroyed: afterCanvasDestroyed,
- 'default': detail
- });
- Chart._Interactions = {};
- Chart.registerInteraction = function (type, constructor) {
- Chart._Interactions[type] = constructor;
- };
- Chart.getInteraction = function (type) {
- return Chart._Interactions[type];
- };
- Chart.prototype.interaction = function (type, cfg) {
- var interactions = this._interactions || {};
- if (interactions[type]) {
- // if reprated, destroy last
- interactions[type].destroy();
- }
- var Ctor = Chart.getInteraction(type);
- var interact = new Ctor(cfg, this);
- interactions[type] = interact;
- this._interactions = interactions;
- return this;
- };
- Chart.prototype.clearInteraction = function (type) {
- var interactions = this._interactions;
- if (!interactions) return;
- if (type) {
- interactions[type] && interactions[type].destroy();
- delete interactions[type];
- } else {
- each(interactions, function (interaction, key) {
- interaction.destroy();
- delete interactions[key];
- });
- }
- return this;
- };
- function _defineProperty$5(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- function isValuesEqual(values, newValues) {
- if (values.length !== newValues.length) {
- return false;
- }
- var lastIndex = values.length - 1;
- return values[0] === newValues[0] && values[lastIndex] === newValues[lastIndex];
- } // 不同交互之间共享的上下文
- var defaultRange = [0, 1];
- class Context {
- // 最开始的原始值
- // 当前显示的范围
- // 缩放最小的点数
- // 最小的缩放比例, 默认通过minCount计算
- // minScale = 0.01;
- // 交互开始时,ticks个数,主要为了每次缩放后,更新ticks个数
- // lastTickCount;
- constructor(chart) {
- var _this = this;
- _defineProperty$5(this, "chart", null);
- _defineProperty$5(this, "values", null);
- _defineProperty$5(this, "range", defaultRange);
- _defineProperty$5(this, "startRange", defaultRange);
- _defineProperty$5(this, "minCount", 10);
- _defineProperty$5(this, "_afterinit", function () {
- // 初始化value值
- var scale = _this.getPinchScale(); // 记录原始全量数据
- var values = [].concat(scale.values);
- _this.values = values; // 最小的缩放比例
- if (!_this.minScale) {
- _this.minScale = _this.minCount / values.length;
- } // 初始化的时候有设置range,则初始化成默认比例
- if (_this.range !== defaultRange) {
- _this.updateRange(_this.range);
- _this.updateTicks();
- }
- });
- _defineProperty$5(this, "_afterdatachange", function () {
- _this.updateRange(_this.range);
- });
- this.chart = chart;
- this._initEvent(chart);
- }
- _initEvent(chart) {
- // 在整体初始化后还需要设置一些初始状态
- chart.on(EVENT_AFTER_INIT, this._afterinit);
- chart.on(EVENT_AFTER_DATA_CHANGE, this._afterdatachange);
- } // 缩放的主轴scale
- getPinchScale() {
- var {
- chart
- } = this; // 默认缩放x轴
- var scale = chart.getXScale();
- return scale;
- } // 跟随轴的scale
- getFollowScale() {
- var {
- chart
- } = this; // 默认缩放x轴
- var scales = chart.getYScales() || [];
- return scales[0];
- }
- start() {
- var {
- range
- } = this;
- var scale = this.getPinchScale();
- var [start, end] = range; // 记录交互起始的范围
- this.startRange = [start, end]; // 记录开始时的ticks个数
- this.lastTickCount = scale.tickCount;
- }
- doZoom(leftScale, rightScale, zoom) {
- var {
- startRange: range,
- minScale
- } = this;
- var [start, end] = range;
- var zoomOffset = 1 - zoom;
- var rangeLen = end - start;
- var rangeOffset = rangeLen * zoomOffset;
- var leftOffset = rangeOffset * leftScale;
- var rightOffset = rangeOffset * rightScale;
- var newStart = Math.max(0, start - leftOffset);
- var newEnd = Math.min(1, end + rightOffset);
- var newRange = [newStart, newEnd]; // 如果已经到了最小比例,则不能再继续再放大
- if (newEnd - newStart < minScale) {
- return;
- }
- this.updateRange(newRange);
- }
- doMove(ratio) {
- // 不管是0, 还是其他,都不用处理
- if (!ratio) return;
- var {
- startRange: range
- } = this;
- var [start, end] = range;
- var rangeLen = end - start;
- var rangeOffset = rangeLen * ratio;
- var newStart = start - rangeOffset;
- var newEnd = end - rangeOffset; // 处理边界值
- var newRange;
- if (newStart < 0) {
- newRange = [0, rangeLen];
- } else if (newEnd > 1) {
- newRange = [1 - rangeLen, 1];
- } else {
- newRange = [newStart, newEnd];
- }
- this.updateRange(newRange);
- }
- updateRange(range) {
- var {
- values
- } = this; // 0, 1 的范围之间
- var [start, end] = range; // start 不能小于0
- start = Math.max(0, start); // end 不能大于1
- end = Math.min(1, end); // 设置当前的范围
- this.range = [start, end];
- var len = values.length;
- var valueStart = start * len;
- var valueEnd = end * len; // 从原始数据里截取需要显示的数据
- var newValues = values.slice(valueStart, valueEnd);
- this.repaint(newValues);
- }
- repaint(newValues) {
- var {
- chart
- } = this;
- var scale = this.getPinchScale();
- var {
- values: currentValues,
- ticks
- } = scale; // 如果新数组和当前显示的数组相同,则不更新
- if (isValuesEqual(currentValues, newValues)) {
- return;
- } // 更新主轴values
- this.updateScale(scale, {
- ticks,
- values: newValues
- });
- this.updateFollowScale(scale, newValues);
- chart.repaint();
- }
- updateFollowScale(pinchScale, pinchValues) {
- var {
- chart
- } = this;
- var followScale = this.getFollowScale();
- var {
- field: pinchField,
- type: pinchScaleType
- } = pinchScale;
- var {
- field: followField
- } = followScale; // 根据主轴的value值,找到所有从轴的value值
- var values = []; // 转成map,让查找性能更高
- var pinchValueMap = {};
- pinchValues.forEach(function (item) {
- pinchValueMap[item] = true;
- });
- var data = chart.get('data');
- data.forEach(function (item) {
- if (pinchScaleType === 'timeCat') {
- var value = toTimeStamp(item[pinchField]);
- if (pinchValueMap[value]) {
- values.push(item[followField]);
- }
- }
- });
- var {
- min,
- max
- } = getRange$1(values);
- this.updateScale(followScale, {
- min,
- max,
- nice: true
- });
- }
- updateScale(scale, cfg) {
- if (!scale) {
- return;
- }
- scale.change(cfg);
- } // 上一次的tick个数
- updateTicks() {
- var {
- chart,
- values
- } = this;
- var scale = this.getPinchScale();
- var {
- values: currentValues,
- tickCount
- } = scale; // 根据当前数据的比例,和定义的tickCount计算应该需要多少个ticks
- var newTickCount = Math.round(tickCount * values.length / currentValues.length);
- var catTicks = getTickMethod('cat');
- var ticks = catTicks({
- tickCount: newTickCount,
- values
- });
- this.updateScale(scale, {
- ticks,
- values: currentValues
- }); // 更新完后,需要重新绘制一次
- chart.repaint();
- }
- destroy() {
- var {
- chart
- } = this;
- chart.off(EVENT_AFTER_INIT, this._afterinit);
- chart.off(EVENT_AFTER_DATA_CHANGE, this._afterdatachange);
- }
- }
- function _defineProperty$6(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- class Base$2 {
- // 交互的上下文
- getDefaultCfg() {
- return {};
- }
- getInteractionContext(chart) {
- var interactionContext = chart.get('interactionContext');
- if (interactionContext) {
- return interactionContext;
- }
- interactionContext = new Context(chart);
- chart.set('interactionContext', interactionContext);
- return interactionContext;
- }
- constructor(cfg, chart) {
- var _this = this;
- _defineProperty$6(this, "type", '');
- _defineProperty$6(this, "startEvent", 'touchstart');
- _defineProperty$6(this, "processEvent", 'touchmove');
- _defineProperty$6(this, "endEvent", 'touchend');
- _defineProperty$6(this, "resetEvent", null);
- _defineProperty$6(this, "context", null);
- _defineProperty$6(this, "_start", function (ev) {
- _this.preStart && _this.preStart(ev);
- _this.start(ev);
- _this.onStart && _this.onStart(ev);
- });
- _defineProperty$6(this, "_process", function (ev) {
- _this.preProcess && _this.preProcess(ev);
- _this.process(ev);
- _this.onProcess && _this.onProcess(ev);
- });
- _defineProperty$6(this, "_end", function (ev) {
- _this.preEnd && _this.preEnd(ev);
- _this.end(ev);
- _this.onEnd && _this.onEnd(ev);
- });
- _defineProperty$6(this, "_reset", function (ev) {
- _this.preReset && _this.preReset(ev);
- _this.reset(ev);
- _this.onReset && _this.onReset(ev);
- });
- mix(this, this.getDefaultCfg(), cfg);
- this.context = this.getInteractionContext(chart);
- this.chart = chart; // 只处理range, 暂时先这么处理后面再看情况调整
- var {
- range
- } = this;
- if (range) {
- this.context.range = range;
- }
- this._bindEvents(chart);
- }
- _bindEvents(chart) {
- var {
- startEvent,
- processEvent,
- endEvent,
- resetEvent
- } = this;
- var canvas = chart.get('canvas'); // 统一绑定事件
- canvas.on(startEvent, this._start);
- canvas.on(processEvent, this._process);
- canvas.on(endEvent, this._end);
- canvas.on(resetEvent, this._reset);
- }
- _clearEvents() {
- var {
- chart,
- startEvent,
- processEvent,
- endEvent,
- resetEvent
- } = this;
- var canvas = chart.get('canvas'); // 统一绑定事件
- canvas.off(startEvent, this._start);
- canvas.off(processEvent, this._process);
- canvas.off(endEvent, this._end);
- canvas.off(resetEvent, this._start);
- }
- // override
- start() {} // override
- process() {} // override
- end() {} // override
- reset() {}
- destroy() {
- this.context.destroy();
- this._clearEvents();
- }
- }
- class Pan extends Base$2 {
- getDefaultCfg() {
- return {
- type: 'pan',
- startEvent: 'panstart',
- processEvent: 'pan',
- endEvent: 'panend'
- };
- }
- start() {
- var {
- context
- } = this;
- context.start();
- }
- process(e) {
- var {
- direction,
- deltaX
- } = e;
- if (direction === 'up' || direction === 'down') {
- return;
- }
- e.preventDefault && e.preventDefault();
- var {
- context
- } = this;
- var chart = context.chart;
- var coord = chart.get('coord');
- var {
- start,
- end
- } = coord;
- var coordWidth = end.x - start.x;
- var ratio = deltaX / coordWidth;
- context.doMove(ratio);
- }
- }
- class Pinch extends Base$2 {
- getDefaultCfg() {
- return {
- type: 'pinch',
- startEvent: 'pinchstart',
- processEvent: 'pinch',
- endEvent: 'pinchend'
- };
- }
- constructor(cfg, chart) {
- super(cfg, chart);
- var {
- context
- } = this;
- mix(context, cfg);
- }
- start() {
- var {
- context
- } = this;
- context.start();
- }
- process(e) {
- e.preventDefault && e.preventDefault();
- var {
- zoom,
- center
- } = e;
- var {
- context
- } = this;
- var {
- chart
- } = context;
- var coord = chart.get('coord');
- var {
- start,
- end
- } = coord;
- var coordWidth = end.x - start.x;
- var leftLen = Math.abs(center.x - start.x);
- var rightLen = Math.abs(end.x - center.x); // 计算左右缩放的比例
- var leftScale = leftLen / coordWidth;
- var rightScale = rightLen / coordWidth;
- context.doZoom(leftScale, rightScale, zoom);
- }
- end() {
- // 缩放完成后再更新ticks
- var {
- context
- } = this;
- context.updateTicks();
- }
- }
- Chart.registerInteraction('pan', Pan);
- Chart.registerInteraction('pinch', Pinch);
- /**
- * Default, without interactins
- */
- var Component$1 = {
- Marker
- }; // register plugins
- Chart.plugins.register([Tooltip$1, Legend, Guide, Animation]); // 默认添加交互
- var F2 = {
- Component: Component$1,
- Global,
- Chart,
- Shape: Shape$1,
- G,
- Util,
- Helper,
- track,
- Animate
- };
- var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
- function unwrapExports (x) {
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
- }
- function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
- }
- var array$1 = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.merge = merge;
- exports.values = values;
- exports.firstValue = firstValue;
- exports.group = group;
- exports.groupToMap = groupToMap;
- exports.remove = remove;
- exports.getRange = getRange;
- function merge(dataArray) {
- var rst = [];
- for (var i = 0, len = dataArray.length; i < len; i++) {
- rst = rst.concat(dataArray[i]);
- }
- return rst;
- }
- function values(data, name) {
- var rst = [];
- var tmpMap = {};
- for (var i = 0, len = data.length; i < len; i++) {
- var obj = data[i];
- var value = obj[name];
- if (!(0, esm.isNil)(value)) {
- if (!(0, esm.isArray)(value)) {
- if (!tmpMap[value]) {
- rst.push(value);
- tmpMap[value] = true;
- }
- } else {
- (0, esm.each)(value, function (val) {
- if (!tmpMap[val]) {
- rst.push(val);
- tmpMap[val] = true;
- }
- });
- }
- }
- }
- return rst;
- }
- function firstValue(data, name) {
- var rst = null;
- for (var i = 0, len = data.length; i < len; i++) {
- var obj = data[i];
- var value = obj[name];
- if (!(0, esm.isNil)(value)) {
- if ((0, esm.isArray)(value)) {
- rst = value[0];
- } else {
- rst = value;
- }
- break;
- }
- }
- return rst;
- }
- function groupToMap(data, fields) {
- if (!fields) {
- return {
- 0: data
- };
- }
- var callback = function callback(row) {
- var unique = '_';
- for (var i = 0, l = fields.length; i < l; i++) {
- unique += row[fields[i]] && row[fields[i]].toString();
- }
- return unique;
- };
- var groups = {};
- for (var i = 0, len = data.length; i < len; i++) {
- var row = data[i];
- var key = callback(row);
- if (groups[key]) {
- groups[key].push(row);
- } else {
- groups[key] = [row];
- }
- }
- return groups;
- }
- function group(data, fields, appendConditions) {
- if (appendConditions === void 0) {
- appendConditions = {};
- }
- if (!fields) {
- return [data];
- }
- var groups = groupToMap(data, fields);
- var array = [];
- if (fields.length === 1 && appendConditions[fields[0]]) {
- var _values = appendConditions[fields[0]];
- (0, esm.each)(_values, function (value) {
- value = '_' + value;
- array.push(groups[value]);
- });
- } else {
- for (var i in groups) {
- array.push(groups[i]);
- }
- }
- return array;
- }
- function remove(arr, obj) {
- if (!arr) {
- return;
- }
- var index = arr.indexOf(obj);
- if (index !== -1) {
- arr.splice(index, 1);
- }
- }
- function getRange(values) {
- if (!values.length) {
- return {
- min: 0,
- max: 0
- };
- }
- var max = Math.max.apply(null, values);
- var min = Math.min.apply(null, values);
- return {
- min: min,
- max: max
- };
- }
- });
- unwrapExports(array$1);
- var array_1 = array$1.merge;
- var array_2 = array$1.values;
- var array_3 = array$1.firstValue;
- var array_4 = array$1.group;
- var array_5 = array$1.groupToMap;
- var array_6 = array$1.remove;
- var array_7 = array$1.getRange;
- var dom = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.isCanvasElement = isCanvasElement;
- exports.getPixelRatio = getPixelRatio;
- exports.getStyle = getStyle;
- exports.getWidth = getWidth;
- exports.getHeight = getHeight;
- exports.getDomById = getDomById;
- exports.getRelativePosition = getRelativePosition;
- exports.addEventListener = addEventListener;
- exports.removeEventListener = removeEventListener;
- exports.createEvent = createEvent;
- exports.measureText = measureText;
- exports.isBrowser = exports.isNode = exports.isMy = exports.isWx = void 0;
- /**
- * Detects support for options object argument in addEventListener.
- * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support
- * @private
- */
- var supportsEventListenerOptions = function () {
- var supports = false;
- try {
- var options = Object.defineProperty({}, 'passive', {
- get: function get() {
- supports = true;
- }
- });
- window.addEventListener('e', null, options);
- } catch (e) {// continue regardless of error
- }
- return supports;
- }(); // Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events.
- // https://github.com/chartjs/Chart.js/issues/4287
- var eventListenerOptions = supportsEventListenerOptions ? {
- passive: true
- } : false;
- /* global wx, my */
- // weixin miniprogram
- var isWx = typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function'; // ant miniprogram
- exports.isWx = isWx;
- var isMy = typeof my === 'object' && typeof my.getSystemInfoSync === 'function'; // in node
- exports.isMy = isMy;
- var isNode = typeof commonjsGlobal && !typeof window; // in browser
- exports.isNode = isNode;
- var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.sessionStorage !== 'undefined';
- exports.isBrowser = isBrowser;
- function isCanvasElement(el) {
- if (!el || typeof el !== 'object') return false;
- if (el.nodeType === 1 && el.nodeName) {
- // HTMLCanvasElement
- return true;
- } // CanvasElement
- return !!el.isCanvasElement;
- }
- function getPixelRatio() {
- return window && window.devicePixelRatio || 1;
- }
- function getStyle(el, property) {
- return el.currentStyle ? el.currentStyle[property] : document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
- }
- function getWidth(el) {
- var width = getStyle(el, 'width');
- if (width === 'auto') {
- width = el.offsetWidth;
- }
- return parseFloat(width);
- }
- function getHeight(el) {
- var height = getStyle(el, 'height');
- if (height === 'auto') {
- height = el.offsetHeight;
- }
- return parseFloat(height);
- }
- function getDomById(id) {
- if (!id) {
- return null;
- }
- return document.getElementById(id);
- }
- function getRelativePosition(point, canvas) {
- var canvasDom = canvas.get('el');
- if (!canvasDom) return point;
- var _canvasDom$getBoundin = canvasDom.getBoundingClientRect(),
- top = _canvasDom$getBoundin.top,
- right = _canvasDom$getBoundin.right,
- bottom = _canvasDom$getBoundin.bottom,
- left = _canvasDom$getBoundin.left;
- var paddingLeft = parseFloat(getStyle(canvasDom, 'padding-left'));
- var paddingTop = parseFloat(getStyle(canvasDom, 'padding-top'));
- var paddingRight = parseFloat(getStyle(canvasDom, 'padding-right'));
- var paddingBottom = parseFloat(getStyle(canvasDom, 'padding-bottom'));
- var width = right - left - paddingLeft - paddingRight;
- var height = bottom - top - paddingTop - paddingBottom;
- var pixelRatio = canvas.get('pixelRatio');
- var mouseX = (point.x - left - paddingLeft) / width * canvasDom.width / pixelRatio;
- var mouseY = (point.y - top - paddingTop) / height * canvasDom.height / pixelRatio;
- return {
- x: mouseX,
- y: mouseY
- };
- }
- function addEventListener(source, type, listener) {
- source.addEventListener(type, listener, eventListenerOptions);
- }
- function removeEventListener(source, type, listener) {
- source.removeEventListener(type, listener, eventListenerOptions);
- }
- function createEventObj(type, chart, x, y, nativeEvent) {
- return {
- type: type,
- chart: chart,
- "native": nativeEvent || null,
- x: x !== undefined ? x : null,
- y: y !== undefined ? y : null
- };
- }
- function createEvent(event, chart) {
- var type = event.type;
- var clientPoint; // 说明是touch相关事件
- if (event.touches) {
- // https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent/changedTouches
- // 这里直接拿changedTouches就可以了,不管是touchstart, touchmove, touchend changedTouches 都是有的
- // 为了以防万一,做个空判断
- var touch = event.changedTouches[0] || {}; // x, y: 相对canvas原点的位置,clientX, clientY 相对于可视窗口的位置
- var x = touch.x,
- y = touch.y,
- clientX = touch.clientX,
- clientY = touch.clientY; // 小程序环境会有x,y,这里就直接返回
- if (x && y) {
- return createEventObj(type, chart, x, y, event);
- }
- clientPoint = {
- x: clientX,
- y: clientY
- };
- } else {
- // mouse相关事件
- clientPoint = {
- x: event.clientX,
- y: event.clientY
- };
- } // 理论上应该是只有有在浏览器环境才会走到这里
- var canvas = chart.get('canvas'); // 通过clientX, clientY 计算x, y
- var point = getRelativePosition(clientPoint, canvas);
- return createEventObj(type, chart, point.x, point.y, event);
- }
- function measureText(text, font, ctx) {
- if (!ctx) {
- ctx = document.createElement('canvas').getContext('2d');
- }
- ctx.font = font || '12px sans-serif';
- return ctx.measureText(text);
- }
- });
- unwrapExports(dom);
- var dom_1 = dom.isCanvasElement;
- var dom_2 = dom.getPixelRatio;
- var dom_3 = dom.getStyle;
- var dom_4 = dom.getWidth;
- var dom_5 = dom.getHeight;
- var dom_6 = dom.getDomById;
- var dom_7 = dom.getRelativePosition;
- var dom_8 = dom.addEventListener;
- var dom_9 = dom.removeEventListener;
- var dom_10 = dom.createEvent;
- var dom_11 = dom.measureText;
- var dom_12 = dom.isBrowser;
- var dom_13 = dom.isNode;
- var dom_14 = dom.isMy;
- var dom_15 = dom.isWx;
- var common = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- var _exportNames = {
- isObjectValueEqual: true,
- parsePadding: true,
- directionEnabled: true,
- toTimeStamp: true,
- upperFirst: true,
- lowerFirst: true,
- isString: true,
- isNumber: true,
- isBoolean: true,
- isFunction: true,
- isDate: true,
- isArray: true,
- isNil: true,
- isObject: true,
- isPlainObject: true,
- isEqual: true,
- deepMix: true,
- mix: true,
- each: true,
- uniq: true,
- find: true,
- Array: true
- };
- exports.isObjectValueEqual = isObjectValueEqual;
- exports.parsePadding = parsePadding;
- exports.directionEnabled = directionEnabled;
- exports.toTimeStamp = toTimeStamp;
- exports.Array = void 0;
- exports.upperFirst = esm.upperFirst;
- exports.lowerFirst = esm.lowerFirst;
- exports.isString = esm.isString;
- exports.isNumber = esm.isNumber;
- exports.isBoolean = esm.isBoolean;
- exports.isFunction = esm.isFunction;
- exports.isDate = esm.isDate;
- exports.isArray = esm.isArray;
- exports.isNil = esm.isNil;
- exports.isObject = esm.isObject;
- exports.isPlainObject = esm.isPlainObject;
- exports.isEqual = esm.isEqual;
- exports.deepMix = esm.deepMix;
- exports.mix = esm.mix;
- exports.each = esm.each;
- exports.uniq = esm.uniq;
- exports.find = esm.find;
- var ArrayUtil = _interopRequireWildcard(array$1);
- exports.Array = ArrayUtil;
- Object.keys(dom).forEach(function (key) {
- if (key === "default" || key === "__esModule") return;
- if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
- if (key in exports && exports[key] === dom[key]) return;
- exports[key] = dom[key];
- });
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- /**
- * @fileOverview Utility for F2
- * @author dxq613 @gmail.com
- * @author sima.zhang1990@gmail.com
- */
- function isObjectValueEqual(a, b) {
- // for vue.js
- a = Object.assign({}, a);
- b = Object.assign({}, b);
- var aProps = Object.getOwnPropertyNames(a);
- var bProps = Object.getOwnPropertyNames(b);
- if (aProps.length !== bProps.length) {
- return false;
- }
- for (var i = 0, len = aProps.length; i < len; i++) {
- var propName = aProps[i];
- if (a[propName] !== b[propName]) {
- return false;
- }
- }
- return true;
- }
- function parsePadding(padding) {
- var top;
- var right;
- var bottom;
- var left;
- if ((0, esm.isNumber)(padding) || (0, esm.isString)(padding)) {
- top = bottom = left = right = padding;
- } else if ((0, esm.isArray)(padding)) {
- top = padding[0];
- right = !(0, esm.isNil)(padding[1]) ? padding[1] : padding[0];
- bottom = !(0, esm.isNil)(padding[2]) ? padding[2] : padding[0];
- left = !(0, esm.isNil)(padding[3]) ? padding[3] : right;
- }
- return [top, right, bottom, left];
- }
- function directionEnabled(mode, dir) {
- if (mode === undefined) {
- return true;
- } else if (typeof mode === 'string') {
- return mode.indexOf(dir) !== -1;
- }
- return false;
- }
- function toTimeStamp(value) {
- if ((0, esm.isString)(value)) {
- if (value.indexOf('T') > 0) {
- value = new Date(value).getTime();
- } else {
- // new Date('2010/01/10') 和 new Date('2010-01-10') 的差别在于:
- // 如果仅有年月日时,前者是带有时区的: Fri Jan 10 2020 02:40:13 GMT+0800 (中国标准时间)
- // 后者会格式化成 Sun Jan 10 2010 08:00:00 GMT+0800 (中国标准时间)
- value = new Date(value.replace(/-/gi, '/')).getTime();
- }
- }
- if ((0, esm.isDate)(value)) {
- value = value.getTime();
- }
- return value;
- }
- });
- unwrapExports(common);
- var common_1 = common.isObjectValueEqual;
- var common_2 = common.parsePadding;
- var common_3 = common.directionEnabled;
- var common_4 = common.toTimeStamp;
- var common_5 = common.Array;
- var common_6 = common.upperFirst;
- var common_7 = common.lowerFirst;
- var common_8 = common.isString;
- var common_9 = common.isNumber;
- var common_10 = common.isBoolean;
- var common_11 = common.isFunction;
- var common_12 = common.isDate;
- var common_13 = common.isArray;
- var common_14 = common.isNil;
- var common_15 = common.isObject;
- var common_16 = common.isPlainObject;
- var common_17 = common.isEqual;
- var common_18 = common.deepMix;
- var common_19 = common.mix;
- var common_20 = common.each;
- var common_21 = common.uniq;
- var common_22 = common.find;
- var emit = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- // 实现简单的事件机制
- var EventEmit = /*#__PURE__*/function () {
- function EventEmit() {
- this.__events = {};
- }
- var _proto = EventEmit.prototype;
- _proto.on = function on(type, listener) {
- if (!type || !listener) {
- return;
- }
- var events = this.__events[type] || [];
- events.push(listener);
- this.__events[type] = events;
- };
- _proto.emit = function emit(type, e) {
- var _this = this;
- if ((0, common.isObject)(type)) {
- e = type;
- type = e && e.type;
- }
- if (!type) {
- return;
- }
- var events = this.__events[type];
- if (!events || !events.length) {
- return;
- }
- events.forEach(function (listener) {
- listener.call(_this, e);
- });
- };
- _proto.off = function off(type, listener) {
- var __events = this.__events;
- var events = __events[type];
- if (!events || !events.length) {
- return;
- } // 如果没有指定方法,则删除所有项
- if (!listener) {
- delete __events[type];
- return;
- } // 删除指定的 listener
- for (var i = 0, len = events.length; i < len; i++) {
- if (events[i] === listener) {
- events.splice(i, 1);
- i--;
- }
- }
- };
- return EventEmit;
- }();
- var _default = EventEmit;
- exports["default"] = _default;
- });
- unwrapExports(emit);
- var controller = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- // 计算滑动的方向
- var calcDirection = function calcDirection(start, end) {
- var xDistance = end.x - start.x;
- var yDistance = end.y - start.y; // x 的距离大于y 说明是横向,否则就是纵向
- if (Math.abs(xDistance) > Math.abs(yDistance)) {
- return xDistance > 0 ? 'right' : 'left';
- }
- return yDistance > 0 ? 'down' : 'up';
- }; // 计算2点之间的距离
- var calcDistance = function calcDistance(point1, point2) {
- var xDistance = Math.abs(point2.x - point1.x);
- var yDistance = Math.abs(point2.y - point1.y);
- return Math.sqrt(xDistance * xDistance + yDistance * yDistance);
- };
- var getCenter = function getCenter(point1, point2) {
- var x = point1.x + (point2.x - point1.x) / 2;
- var y = point1.y + (point2.y - point1.y) / 2;
- return {
- x: x,
- y: y
- };
- };
- var convertPoints = function convertPoints(ev, canvas) {
- var touches = ev.touches; // 认为是mouse事件
- if (!touches) {
- var point = (0, dom.getRelativePosition)({
- x: ev.clientX,
- y: ev.clientY
- }, canvas);
- return [point];
- }
- var points = [];
- var len = touches.length;
- for (var i = 0; i < len; i++) {
- var touch = touches[i]; // x, y: 相对canvas原点的位置,clientX, clientY 相对于可视窗口的位置
- var x = touch.x,
- y = touch.y,
- clientX = touch.clientX,
- clientY = touch.clientY;
- var _point = void 0; // 小程序环境会有x,y
- if ((0, common.isNumber)(x) || (0, common.isNumber)(y)) {
- _point = {
- x: x,
- y: y
- };
- } else {
- // 浏览器环境再计算下canvas的相对位置
- _point = (0, dom.getRelativePosition)({
- x: clientX,
- y: clientY
- }, canvas);
- }
- points.push(_point);
- }
- return points;
- };
- var PRESS_DELAY = 250;
- var EventController = /*#__PURE__*/function () {
- function EventController(_ref) {
- var _this = this;
- var canvas = _ref.canvas,
- el = _ref.el;
- _defineProperty(this, "_click", function (ev) {
- var points = convertPoints(ev, _this.canvas);
- ev.points = points;
- _this.emitEvent('click', ev);
- });
- _defineProperty(this, "_start", function (ev) {
- var points = convertPoints(ev, _this.canvas);
- if (!points) {
- return;
- }
- ev.points = points;
- _this.emitEvent('touchstart', ev); // 防止上次的内容没有清理掉,重新reset下
- _this.reset(); // 记录touch start 的时间
- _this.startTime = Date.now(); // 记录touch start 的点
- _this.startPoints = points;
- if (points.length > 1) {
- _this.startDistance = calcDistance(points[0], points[1]);
- _this.center = getCenter(points[0], points[1]);
- } else {
- // 如果touchstart后停顿250ms, 则也触发press事件
- _this.pressTimeout = setTimeout(function () {
- // 这里固定触发press事件
- var eventType = 'press';
- var direction = 'none';
- ev.direction = direction;
- _this.emitStart(eventType, ev);
- _this.emitEvent(eventType, ev);
- _this.eventType = eventType;
- _this.direction = direction;
- }, PRESS_DELAY);
- }
- });
- _defineProperty(this, "_move", function (ev) {
- var points = convertPoints(ev, _this.canvas);
- if (!points) return;
- _this.clearPressTimeout();
- ev.points = points;
- _this.emitEvent('touchmove', ev);
- var startPoints = _this.startPoints;
- if (!startPoints) return; // 多指触控
- if (points.length > 1) {
- // touchstart的距离
- var startDistance = _this.startDistance;
- var currentDistance = calcDistance(points[0], points[1]);
- ev.zoom = currentDistance / startDistance;
- ev.center = _this.center; // 触发缩放事件
- _this.emitStart('pinch', ev);
- _this.emitEvent('pinch', ev);
- } else {
- var deltaX = points[0].x - startPoints[0].x;
- var deltaY = points[0].y - startPoints[0].y;
- var direction = _this.direction || calcDirection(startPoints[0], points[0]);
- _this.direction = direction; // 获取press或者pan的事件类型
- // press 按住滑动, pan表示平移
- // 如果start后立刻move,则触发pan, 如果有停顿,则触发press
- var eventType = _this.getEventType(points);
- ev.direction = direction;
- ev.deltaX = deltaX;
- ev.deltaY = deltaY;
- _this.emitStart(eventType, ev);
- _this.emitEvent(eventType, ev); // 记录最后2次move的时间和坐标,为了给swipe事件用
- var prevMoveTime = _this.lastMoveTime;
- var now = Date.now(); // 最后2次的时间间隔一定要大于0,否则swipe没发计算
- if (now - prevMoveTime > 0) {
- _this.prevMoveTime = prevMoveTime;
- _this.prevMovePoints = _this.lastMovePoints;
- _this.lastMoveTime = now;
- _this.lastMovePoints = points;
- }
- }
- });
- _defineProperty(this, "_end", function (ev) {
- _this.emitEnd(ev);
- _this.emitEvent('touchend', ev); // swipe事件处理, 在touchend之后触发
- var lastMoveTime = _this.lastMoveTime;
- var now = Date.now(); // 做这个判断是为了最后一次touchmove后到end前,还有一个停顿的过程
- // 100 是拍的一个值,理论这个值会很短,一般不卡顿的话在10ms以内
- if (now - lastMoveTime < 100) {
- var prevMoveTime = _this.prevMoveTime || _this.startTime;
- var intervalTime = lastMoveTime - prevMoveTime; // 时间间隔一定要大于0, 否则计算没意义
- if (intervalTime > 0) {
- var prevMovePoints = _this.prevMovePoints || _this.startPoints;
- var lastMovePoints = _this.lastMovePoints; // move速率
- var velocity = calcDistance(prevMovePoints[0], lastMovePoints[0]) / intervalTime; // 0.3 是参考hammerjs的设置
- if (velocity > 0.3) {
- ev.velocity = velocity;
- ev.direction = calcDirection(prevMovePoints[0], lastMovePoints[0]);
- _this.emitEvent('swipe', ev);
- }
- }
- }
- _this.reset();
- var touches = ev.touches; // 当多指只释放了1指时也会触发end, 这时重新触发一次start
- if (touches && touches.length > 0) {
- _this._start(ev);
- }
- });
- _defineProperty(this, "_cancel", function (ev) {
- _this.emitEvent('touchcancel', ev);
- _this.reset();
- });
- // canvasEl
- this.canvas = canvas;
- this.delegateEvent(el); // 用来记录当前触发的事件
- this.processEvent = {};
- }
- var _proto = EventController.prototype;
- _proto.delegateEvent = function delegateEvent(canvasEl) {
- // 代理这几个事件
- canvasEl.addEventListener('click', this._click);
- canvasEl.addEventListener('touchstart', this._start);
- canvasEl.addEventListener('touchmove', this._move);
- canvasEl.addEventListener('touchend', this._end);
- canvasEl.addEventListener('touchcancel', this._cancel);
- };
- _proto.emitEvent = function emitEvent(type, ev) {
- var canvas = this.canvas;
- canvas.emit(type, ev);
- };
- _proto.getEventType = function getEventType(points) {
- var eventType = this.eventType,
- canvas = this.canvas,
- startTime = this.startTime,
- startPoints = this.startPoints;
- if (eventType) {
- return eventType;
- }
- var type;
- var panEventListeners = canvas.__events.pan; // 如果没有pan事件的监听,默认都是press
- if (!panEventListeners || !panEventListeners.length) {
- type = 'press';
- } else {
- // 如果有pan事件的处理,press则需要停顿250ms, 且移动距离小于10
- var now = Date.now();
- if (now - startTime > PRESS_DELAY && calcDistance(startPoints[0], points[0]) < 10) {
- type = 'press';
- } else {
- type = 'pan';
- }
- }
- this.eventType = type;
- return type;
- };
- _proto.enable = function enable(eventType) {
- this.processEvent[eventType] = true;
- } // 是否进行中的事件
- ;
- _proto.isProcess = function isProcess(eventType) {
- return this.processEvent[eventType];
- } // 触发start事件
- ;
- _proto.emitStart = function emitStart(type, ev) {
- if (this.isProcess(type)) {
- return;
- }
- this.enable(type);
- this.emitEvent(type + "start", ev);
- } // 触发end事件
- ;
- _proto.emitEnd = function emitEnd(ev) {
- var _this2 = this;
- var processEvent = this.processEvent;
- Object.keys(processEvent).forEach(function (type) {
- _this2.emitEvent(type + "end", ev);
- delete processEvent[type];
- });
- };
- _proto.clearPressTimeout = function clearPressTimeout() {
- if (this.pressTimeout) {
- clearTimeout(this.pressTimeout);
- this.pressTimeout = 0;
- }
- };
- _proto.reset = function reset() {
- this.clearPressTimeout();
- this.startTime = 0;
- this.startPoints = null;
- this.startDistance = 0;
- this.direction = null;
- this.eventType = null;
- this.pinch = false;
- this.prevMoveTime = 0;
- this.prevMovePoints = null;
- this.lastMoveTime = 0;
- this.lastMovePoints = null;
- };
- return EventController;
- }();
- var _default = EventController;
- exports["default"] = _default;
- });
- unwrapExports(controller);
- var canvasElement = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _emit = _interopRequireDefault(emit);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var CanvasElement = /*#__PURE__*/function (_EventEmit) {
- _inheritsLoose(CanvasElement, _EventEmit);
- function CanvasElement(ctx) {
- var _this;
- _this = _EventEmit.call(this) || this;
- _this.context = ctx; // canvas实际的宽高 (width/height) * pixelRatio
- _this.width = 0;
- _this.height = 0;
- _this.style = {};
- _this.currentStyle = {}; // 用来标识是CanvasElement实例
- _this.isCanvasElement = true;
- return _this;
- }
- var _proto = CanvasElement.prototype;
- _proto.getContext = function getContext()
- /* type */
- {
- return this.context;
- };
- _proto.getBoundingClientRect = function getBoundingClientRect() {
- var width = this.width;
- var height = this.height; // 默认都处理成可视窗口的顶部位置
- return {
- top: 0,
- right: width,
- bottom: height,
- left: 0
- };
- };
- _proto.addEventListener = function addEventListener(type, listener) {
- this.on(type, listener);
- };
- _proto.removeEventListener = function removeEventListener(type, listener) {
- this.off(type, listener);
- };
- _proto.dispatchEvent = function dispatchEvent(type, e) {
- this.emit(type, e);
- };
- return CanvasElement;
- }(_emit["default"]);
- function supportEventListener(canvas) {
- if (!canvas) {
- return false;
- } // 非 HTMLCanvasElement
- if (canvas.nodeType !== 1 || !canvas.nodeName || canvas.nodeName.toLowerCase() !== 'canvas') {
- return false;
- } // 微信小程序canvas.getContext('2d')时也是CanvasRenderingContext2D
- // 也会有ctx.canvas, 而且nodeType也是1,所以还要在看下是否支持addEventListener
- var support = false;
- try {
- canvas.addEventListener('eventTest', function () {
- support = true;
- });
- canvas.dispatchEvent(new Event('eventTest'));
- } catch (error) {
- support = false;
- }
- return support;
- }
- var _default = {
- create: function create(ctx) {
- if (!ctx) {
- return null;
- }
- if (supportEventListener(ctx.canvas)) {
- return ctx.canvas;
- }
- return new CanvasElement(ctx);
- }
- };
- exports["default"] = _default;
- });
- unwrapExports(canvasElement);
- var matrix = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var Matrix = {
- generateDefault: function generateDefault() {
- return [1, 0, 0, 1, 0, 0];
- },
- isChanged: function isChanged(m) {
- return m[0] !== 1 || m[1] !== 0 || m[2] !== 0 || m[3] !== 1 || m[4] !== 0 || m[5] !== 0;
- },
- multiply: function multiply(m1, m2) {
- var m11 = m1[0] * m2[0] + m1[2] * m2[1];
- var m12 = m1[1] * m2[0] + m1[3] * m2[1];
- var m21 = m1[0] * m2[2] + m1[2] * m2[3];
- var m22 = m1[1] * m2[2] + m1[3] * m2[3];
- var dx = m1[0] * m2[4] + m1[2] * m2[5] + m1[4];
- var dy = m1[1] * m2[4] + m1[3] * m2[5] + m1[5];
- return [m11, m12, m21, m22, dx, dy];
- },
- scale: function scale(out, m, v) {
- out[0] = m[0] * v[0];
- out[1] = m[1] * v[0];
- out[2] = m[2] * v[1];
- out[3] = m[3] * v[1];
- out[4] = m[4];
- out[5] = m[5];
- return out;
- },
- rotate: function rotate(out, m, radian) {
- var c = Math.cos(radian);
- var s = Math.sin(radian);
- var m11 = m[0] * c + m[2] * s;
- var m12 = m[1] * c + m[3] * s;
- var m21 = m[0] * -s + m[2] * c;
- var m22 = m[1] * -s + m[3] * c;
- out[0] = m11;
- out[1] = m12;
- out[2] = m21;
- out[3] = m22;
- out[4] = m[4];
- out[5] = m[5];
- return out;
- },
- translate: function translate(out, m, v) {
- out[0] = m[0];
- out[1] = m[1];
- out[2] = m[2];
- out[3] = m[3];
- out[4] = m[4] + m[0] * v[0] + m[2] * v[1];
- out[5] = m[5] + m[1] * v[0] + m[3] * v[1];
- return out;
- },
- transform: function transform(m, actions) {
- var out = [].concat(m);
- for (var i = 0, len = actions.length; i < len; i++) {
- var action = actions[i];
- switch (action[0]) {
- case 't':
- Matrix.translate(out, out, [action[1], action[2]]);
- break;
- case 's':
- Matrix.scale(out, out, [action[1], action[2]]);
- break;
- case 'r':
- Matrix.rotate(out, out, action[1]);
- break;
- }
- }
- return out;
- }
- };
- var _default = Matrix;
- exports["default"] = _default;
- });
- unwrapExports(matrix);
- var vector2 = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- /**
- * 2 Dimensional Vector
- * @module vector2
- */
- var _default = {
- /**
- * Creates a new, empty vector2
- *
- * @return {vector2} a new 2D vector
- */
- create: function create() {
- return [0, 0];
- },
- /**
- * Calculates the length of a vector2
- *
- * @param {vector2} v vector to calculate length of
- * @return {Number} length of v
- */
- length: function length(v) {
- var x = v[0];
- var y = v[1];
- return Math.sqrt(x * x + y * y);
- },
- /**
- * Normalize a vector2
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v vector to normalize
- * @return {vector2} out
- */
- normalize: function normalize(out, v) {
- var len = this.length(v);
- if (len === 0) {
- out[0] = 0;
- out[1] = 0;
- } else {
- out[0] = v[0] / len;
- out[1] = v[1] / len;
- }
- return out;
- },
- /**
- * Adds two vector2's
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- add: function add(out, v1, v2) {
- out[0] = v1[0] + v2[0];
- out[1] = v1[1] + v2[1];
- return out;
- },
- /**
- * Subtracts vector v2 from vector v1
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- sub: function sub(out, v1, v2) {
- out[0] = v1[0] - v2[0];
- out[1] = v1[1] - v2[1];
- return out;
- },
- /**
- * Scales a vector2 by a scalar number
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v the vector to scale
- * @param {Number} s amount to scale the vector by
- * @return {vector2} out
- */
- scale: function scale(out, v, s) {
- out[0] = v[0] * s;
- out[1] = v[1] * s;
- return out;
- },
- /**
- * Calculates the dot product of two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Number} dot product of v1 and v2
- */
- dot: function dot(v1, v2) {
- return v1[0] * v2[0] + v1[1] * v2[1];
- },
- /**
- * Calculates the direction of two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Boolean} the direction of v1 and v2
- */
- direction: function direction(v1, v2) {
- return v1[0] * v2[1] - v2[0] * v1[1];
- },
- /**
- * Calculates the angle of two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Number} angle of v1 and v2
- */
- angle: function angle(v1, v2) {
- var theta = this.dot(v1, v2) / (this.length(v1) * this.length(v2));
- return Math.acos(theta);
- },
- /**
- * Calculates the angle of two vector2's with direction
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @param {Boolean} direction the direction of two vector2's
- * @return {Number} angle of v1 and v2
- */
- angleTo: function angleTo(v1, v2, direction) {
- var angle = this.angle(v1, v2);
- var angleLargeThanPI = this.direction(v1, v2) >= 0;
- if (direction) {
- if (angleLargeThanPI) {
- return Math.PI * 2 - angle;
- }
- return angle;
- }
- if (angleLargeThanPI) {
- return angle;
- }
- return Math.PI * 2 - angle;
- },
- /**
- * whether a vector2 is zero vector
- *
- * @param {vector2} v vector to calculate
- * @return {Boolean} is or not a zero vector
- */
- zero: function zero(v) {
- return v[0] === 0 && v[1] === 0;
- },
- /**
- * Calculates the euclidian distance between two vector2's
- *
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {Number} distance between a and b
- */
- distance: function distance(v1, v2) {
- var x = v2[0] - v1[0];
- var y = v2[1] - v1[1];
- return Math.sqrt(x * x + y * y);
- },
- /**
- * Creates a new vector2 initialized with values from an existing vector
- *
- * @param {vector2} v vector to clone
- * @return {Array} a new 2D vector
- */
- clone: function clone(v) {
- return [v[0], v[1]];
- },
- /**
- * Return the minimum of two vector2's
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- min: function min(out, v1, v2) {
- out[0] = Math.min(v1[0], v2[0]);
- out[1] = Math.min(v1[1], v2[1]);
- return out;
- },
- /**
- * Return the maximum of two vector2's
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v1 the first operand
- * @param {vector2} v2 the second operand
- * @return {vector2} out
- */
- max: function max(out, v1, v2) {
- out[0] = Math.max(v1[0], v2[0]);
- out[1] = Math.max(v1[1], v2[1]);
- return out;
- },
- /**
- * Transforms the vector2 with a mat2d
- *
- * @param {vector2} out the receiving vector
- * @param {vector2} v the vector to transform
- * @param {mat2d} m matrix to transform with
- * @return {vector2} out
- */
- transformMat2d: function transformMat2d(out, v, m) {
- var x = v[0];
- var y = v[1];
- out[0] = m[0] * x + m[2] * y + m[4];
- out[1] = m[1] * x + m[3] * y + m[5];
- return out;
- }
- };
- exports["default"] = _default;
- });
- unwrapExports(vector2);
- var styleParse = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.parseStyle = parseStyle;
- exports["default"] = void 0;
- function _mod(n, m) {
- return (n % m + m) % m;
- }
- function _addStop(steps, gradient) {
- (0, common.each)(steps, function (item) {
- item = item.split(':');
- gradient.addColorStop(Number(item[0]), item[1]);
- });
- } // the string format: 'l(0) 0:#ffffff 0.5:#7ec2f3 1:#1890ff'
- function _parseLineGradient(color, shape, context) {
- var arr = color.split(' ');
- var angle = arr[0].slice(2, arr[0].length - 1);
- angle = _mod(parseFloat(angle) * Math.PI / 180, Math.PI * 2);
- var steps = arr.slice(1);
- var _shape$getBBox = shape.getBBox(),
- minX = _shape$getBBox.minX,
- minY = _shape$getBBox.minY,
- maxX = _shape$getBBox.maxX,
- maxY = _shape$getBBox.maxY;
- var start;
- var end;
- if (angle >= 0 && angle < 0.5 * Math.PI) {
- start = {
- x: minX,
- y: minY
- };
- end = {
- x: maxX,
- y: maxY
- };
- } else if (0.5 * Math.PI <= angle && angle < Math.PI) {
- start = {
- x: maxX,
- y: minY
- };
- end = {
- x: minX,
- y: maxY
- };
- } else if (Math.PI <= angle && angle < 1.5 * Math.PI) {
- start = {
- x: maxX,
- y: maxY
- };
- end = {
- x: minX,
- y: minY
- };
- } else {
- start = {
- x: minX,
- y: maxY
- };
- end = {
- x: maxX,
- y: minY
- };
- }
- var tanTheta = Math.tan(angle);
- var tanTheta2 = tanTheta * tanTheta;
- var x = (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.x;
- var y = tanTheta * (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.y;
- var gradient = context.createLinearGradient(start.x, start.y, x, y);
- _addStop(steps, gradient);
- return gradient;
- } // the string format: 'r(0.5, 0.5, 0.1) 0:#ffffff 1:#1890ff'
- function _parseRadialGradient(color, shape, context) {
- var arr = color.split(' ');
- var circleCfg = arr[0].slice(2, arr[0].length - 1);
- circleCfg = circleCfg.split(',');
- var fx = parseFloat(circleCfg[0]);
- var fy = parseFloat(circleCfg[1]);
- var fr = parseFloat(circleCfg[2]);
- var steps = arr.slice(1); // if radius is 0, no gradient, stroke with the last color
- if (fr === 0) {
- var _color = steps[steps.length - 1];
- return _color.split(':')[1];
- }
- var _shape$getBBox2 = shape.getBBox(),
- width = _shape$getBBox2.width,
- height = _shape$getBBox2.height,
- minX = _shape$getBBox2.minX,
- minY = _shape$getBBox2.minY;
- var r = Math.sqrt(width * width + height * height) / 2;
- var gradient = context.createRadialGradient(minX + width * fx, minY + height * fy, fr * r, minX + width / 2, minY + height / 2, r);
- _addStop(steps, gradient);
- return gradient;
- }
- function parseStyle(color, shape, context) {
- if (color[1] === '(') {
- try {
- var firstCode = color[0];
- if (firstCode === 'l') {
- return _parseLineGradient(color, shape, context);
- } else if (firstCode === 'r') {
- return _parseRadialGradient(color, shape, context);
- }
- } catch (ev) {
- console.error('error in parsing gradient string, please check if there are any extra whitespaces.');
- console.error(ev);
- }
- }
- return color;
- }
- var _default = {
- parseStyle: parseStyle
- };
- exports["default"] = _default;
- });
- unwrapExports(styleParse);
- var styleParse_1 = styleParse.parseStyle;
- var element = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _matrix = _interopRequireDefault(matrix);
- var _vector = _interopRequireDefault(vector2);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- var ALIAS_ATTRS_MAP = {
- stroke: 'strokeStyle',
- fill: 'fillStyle',
- opacity: 'globalAlpha'
- };
- var SHAPE_ATTRS = ['fillStyle', 'font', 'globalAlpha', 'lineCap', 'lineWidth', 'lineJoin', 'miterLimit', 'shadowBlur', 'shadowColor', 'shadowOffsetX', 'shadowOffsetY', 'strokeStyle', 'textAlign', 'textBaseline', 'lineDash', 'shadow' // 兼容支付宝小程序
- ];
- var CLIP_SHAPES = ['circle', 'sector', 'polygon', 'rect', 'polyline'];
- var Element = /*#__PURE__*/function () {
- var _proto = Element.prototype;
- _proto._initProperties = function _initProperties() {
- this._attrs = {
- zIndex: 0,
- visible: true,
- destroyed: false
- };
- };
- function Element(cfg) {
- this._initProperties();
- (0, common.mix)(this._attrs, cfg);
- var attrs = this._attrs.attrs;
- if (attrs) {
- this.initAttrs(attrs);
- }
- this.initTransform();
- }
- _proto.get = function get(name) {
- return this._attrs[name];
- };
- _proto.set = function set(name, value) {
- this._attrs[name] = value;
- };
- _proto.isGroup = function isGroup() {
- return this.get('isGroup');
- };
- _proto.isShape = function isShape() {
- return this.get('isShape');
- };
- _proto.initAttrs = function initAttrs(attrs) {
- this.attr((0, common.mix)(this.getDefaultAttrs(), attrs));
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {};
- };
- _proto._setAttr = function _setAttr(name, value) {
- var attrs = this._attrs.attrs;
- if (name === 'clip') {
- value = this._setAttrClip(value);
- } else {
- var alias = ALIAS_ATTRS_MAP[name];
- if (alias) {
- attrs[alias] = value;
- }
- }
- attrs[name] = value;
- };
- _proto._getAttr = function _getAttr(name) {
- return this._attrs.attrs[name];
- } // _afterAttrsSet() {}
- ;
- _proto._setAttrClip = function _setAttrClip(clip) {
- if (clip && CLIP_SHAPES.indexOf(clip._attrs.type) > -1) {
- if (clip.get('canvas') === null) {
- clip = Object.assign({}, clip);
- }
- clip.set('parent', this.get('parent'));
- clip.set('context', this.get('context'));
- return clip;
- }
- return null;
- };
- _proto.attr = function attr(name, value) {
- var self = this;
- if (self.get('destroyed')) return null;
- var argumentsLen = arguments.length;
- if (argumentsLen === 0) {
- return self._attrs.attrs;
- }
- if ((0, common.isObject)(name)) {
- this._attrs.bbox = null;
- for (var k in name) {
- self._setAttr(k, name[k]);
- }
- if (self._afterAttrsSet) {
- self._afterAttrsSet();
- }
- return self;
- }
- if (argumentsLen === 2) {
- this._attrs.bbox = null;
- self._setAttr(name, value);
- if (self._afterAttrsSet) {
- self._afterAttrsSet();
- }
- return self;
- }
- return self._getAttr(name);
- };
- _proto.getParent = function getParent() {
- return this.get('parent');
- };
- _proto.draw = function draw(context) {
- if (this.get('destroyed')) {
- return;
- }
- if (this.get('visible')) {
- this.setContext(context);
- this.drawInner(context);
- this.restoreContext(context);
- }
- };
- _proto.setContext = function setContext(context) {
- var clip = this._attrs.attrs.clip;
- context.save();
- if (clip) {
- clip.resetTransform(context);
- clip.createPath(context);
- context.clip();
- }
- this.resetContext(context);
- this.resetTransform(context);
- };
- _proto.restoreContext = function restoreContext(context) {
- context.restore();
- };
- _proto.resetContext = function resetContext(context) {
- var elAttrs = this._attrs.attrs;
- if (!this._attrs.isGroup) {
- for (var k in elAttrs) {
- if (SHAPE_ATTRS.indexOf(k) > -1) {
- var v = elAttrs[k];
- if (k === 'fillStyle' || k === 'strokeStyle') {
- v = (0, styleParse.parseStyle)(v, this, context);
- }
- if (k === 'lineDash' && context.setLineDash && (0, common.isArray)(v)) {
- context.setLineDash(v);
- } else {
- context[k] = v;
- }
- }
- }
- }
- };
- _proto.hasFill = function hasFill() {
- return this.get('canFill') && this._attrs.attrs.fillStyle;
- };
- _proto.hasStroke = function hasStroke() {
- return this.get('canStroke') && this._attrs.attrs.strokeStyle;
- };
- _proto.drawInner = function drawInner()
- /* context */
- {};
- _proto.show = function show() {
- this.set('visible', true);
- return this;
- };
- _proto.hide = function hide() {
- this.set('visible', false);
- return this;
- };
- _proto.isVisible = function isVisible() {
- return this.get('visible');
- };
- _proto._removeFromParent = function _removeFromParent() {
- var parent = this.get('parent');
- if (parent) {
- var children = parent.get('children');
- common.Array.remove(children, this);
- }
- return this;
- };
- _proto.remove = function remove(destroy) {
- if (destroy) {
- this.destroy();
- } else {
- this._removeFromParent();
- }
- };
- _proto.destroy = function destroy() {
- var destroyed = this.get('destroyed');
- if (destroyed) {
- return null;
- }
- this._removeFromParent();
- this._attrs = {};
- this.set('destroyed', true);
- };
- _proto.getBBox = function getBBox() {
- return {
- minX: 0,
- maxX: 0,
- minY: 0,
- maxY: 0,
- width: 0,
- height: 0
- };
- };
- _proto.initTransform = function initTransform() {
- var attrs = this._attrs.attrs || {};
- if (!attrs.matrix) {
- attrs.matrix = [1, 0, 0, 1, 0, 0];
- }
- this._attrs.attrs = attrs;
- };
- _proto.getMatrix = function getMatrix() {
- return this._attrs.attrs.matrix;
- };
- _proto.setMatrix = function setMatrix(m) {
- this._attrs.attrs.matrix = [m[0], m[1], m[2], m[3], m[4], m[5]];
- };
- _proto.transform = function transform(actions) {
- var matrix = this._attrs.attrs.matrix;
- this._attrs.attrs.matrix = _matrix["default"].transform(matrix, actions);
- return this;
- };
- _proto.setTransform = function setTransform(actions) {
- this._attrs.attrs.matrix = [1, 0, 0, 1, 0, 0];
- return this.transform(actions);
- };
- _proto.translate = function translate(x, y) {
- var matrix = this._attrs.attrs.matrix;
- _matrix["default"].translate(matrix, matrix, [x, y]);
- };
- _proto.rotate = function rotate(rad) {
- var matrix = this._attrs.attrs.matrix;
- _matrix["default"].rotate(matrix, matrix, rad);
- };
- _proto.scale = function scale(sx, sy) {
- var matrix = this._attrs.attrs.matrix;
- _matrix["default"].scale(matrix, matrix, [sx, sy]);
- };
- _proto.moveTo = function moveTo(x, y) {
- var cx = this._attrs.x || 0;
- var cy = this._attrs.y || 0;
- this.translate(x - cx, y - cy);
- this.set('x', x);
- this.set('y', y);
- };
- _proto.apply = function apply(v) {
- var m = this._attrs.attrs.matrix;
- _vector["default"].transformMat2d(v, v, m);
- return this;
- };
- _proto.resetTransform = function resetTransform(context) {
- var mo = this._attrs.attrs.matrix;
- if (_matrix["default"].isChanged(mo)) {
- context.transform(mo[0], mo[1], mo[2], mo[3], mo[4], mo[5]);
- }
- };
- _proto.isDestroyed = function isDestroyed() {
- return this.get('destroyed');
- };
- return Element;
- }();
- var _default = Element;
- exports["default"] = _default;
- });
- unwrapExports(element);
- var shape = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _element = _interopRequireDefault(element);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Shape = /*#__PURE__*/function (_Element) {
- _inheritsLoose(Shape, _Element);
- function Shape() {
- return _Element.apply(this, arguments) || this;
- }
- var _proto = Shape.prototype;
- _proto._initProperties = function _initProperties() {
- this._attrs = {
- zIndex: 0,
- visible: true,
- destroyed: false,
- isShape: true,
- attrs: {}
- };
- };
- _proto.getType = function getType() {
- return this._attrs.type;
- };
- _proto.drawInner = function drawInner(context) {
- var self = this;
- var attrs = self.get('attrs');
- self.createPath(context);
- var originOpacity = context.globalAlpha;
- if (self.hasFill()) {
- var fillOpacity = attrs.fillOpacity;
- if (!(0, common.isNil)(fillOpacity) && fillOpacity !== 1) {
- context.globalAlpha = fillOpacity;
- context.fill();
- context.globalAlpha = originOpacity;
- } else {
- context.fill();
- }
- }
- if (self.hasStroke()) {
- var lineWidth = attrs.lineWidth;
- if (lineWidth > 0) {
- var strokeOpacity = attrs.strokeOpacity;
- if (!(0, common.isNil)(strokeOpacity) && strokeOpacity !== 1) {
- context.globalAlpha = strokeOpacity;
- }
- context.stroke();
- }
- }
- };
- _proto.getBBox = function getBBox() {
- var bbox = this._attrs.bbox;
- if (!bbox) {
- bbox = this.calculateBox();
- if (bbox) {
- bbox.x = bbox.minX;
- bbox.y = bbox.minY;
- bbox.width = bbox.maxX - bbox.minX;
- bbox.height = bbox.maxY - bbox.minY;
- }
- this._attrs.bbox = bbox;
- }
- return bbox;
- };
- _proto.calculateBox = function calculateBox() {
- return null;
- };
- _proto.createPath = function createPath() {};
- return Shape;
- }(_element["default"]);
- var _default = Shape;
- exports["default"] = _default;
- });
- unwrapExports(shape);
- var container = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- var SHAPE_MAP = {};
- var INDEX = '_INDEX';
- function getComparer(compare) {
- return function (left, right) {
- var result = compare(left, right);
- return result === 0 ? left[INDEX] - right[INDEX] : result;
- };
- }
- var _default = {
- getGroupClass: function getGroupClass() {},
- getChildren: function getChildren() {
- return this.get('children');
- },
- addShape: function addShape(type, cfg) {
- if (cfg === void 0) {
- cfg = {};
- }
- var canvas = this.get('canvas');
- var shapeType = SHAPE_MAP[type];
- if (!shapeType) {
- shapeType = (0, common.upperFirst)(type);
- SHAPE_MAP[type] = shapeType;
- }
- cfg.canvas = canvas;
- if (shapeType === 'Text' && canvas && canvas.get('fontFamily')) {
- cfg.attrs.fontFamily = cfg.attrs.fontFamily || canvas.get('fontFamily');
- }
- var shape = new _shape["default"][shapeType](cfg);
- this.add(shape);
- return shape;
- },
- addGroup: function addGroup(cfg) {
- var canvas = this.get('canvas');
- var groupClass = this.getGroupClass();
- cfg = (0, common.mix)({}, cfg);
- cfg.canvas = canvas;
- cfg.parent = this;
- var rst = new groupClass(cfg);
- this.add(rst);
- return rst;
- },
- contain: function contain(item) {
- var children = this.get('children');
- return children.indexOf(item) > -1;
- },
- sort: function sort() {
- var children = this.get('children');
- for (var i = 0, len = children.length; i < len; i++) {
- var child = children[i];
- child[INDEX] = i;
- }
- children.sort(getComparer(function (obj1, obj2) {
- return obj1.get('zIndex') - obj2.get('zIndex');
- }));
- return this;
- },
- drawInner: function drawInner(context) {
- var children = this.get('children');
- for (var i = 0, len = children.length; i < len; i++) {
- var child = children[i];
- child.draw(context);
- }
- return this;
- },
- clear: function clear() {
- var children = this.get('children');
- while (children.length !== 0) {
- children[children.length - 1].remove(true);
- }
- return this;
- },
- add: function add(items) {
- var self = this;
- var children = self.get('children');
- if (!(0, common.isArray)(items)) {
- items = [items];
- }
- for (var i = 0, len = items.length; i < len; i++) {
- var item = items[i];
- var parent = item.get('parent');
- if (parent) {
- var descendants = parent.get('children');
- common.Array.remove(descendants, item);
- }
- self._setEvn(item);
- children.push(item);
- }
- return self;
- },
- _setEvn: function _setEvn(item) {
- var self = this;
- item._attrs.parent = self;
- item._attrs.context = self._attrs.context;
- item._attrs.canvas = self._attrs.canvas;
- var clip = item._attrs.attrs.clip;
- if (clip) {
- clip.set('parent', self);
- clip.set('context', self.get('context'));
- }
- if (item._attrs.isGroup) {
- var children = item._attrs.children;
- for (var i = 0, len = children.length; i < len; i++) {
- item._setEvn(children[i]);
- }
- }
- }
- };
- exports["default"] = _default;
- });
- unwrapExports(container);
- var group$2 = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _element = _interopRequireDefault(element);
- var _container = _interopRequireDefault(container);
- var _vector = _interopRequireDefault(vector2);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Group = /*#__PURE__*/function (_Element) {
- _inheritsLoose(Group, _Element);
- function Group() {
- return _Element.apply(this, arguments) || this;
- }
- var _proto = Group.prototype;
- _proto._initProperties = function _initProperties() {
- this._attrs = {
- zIndex: 0,
- visible: true,
- destroyed: false,
- isGroup: true,
- children: []
- };
- };
- _proto.getBBox = function getBBox() {
- var self = this;
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- var children = self.get('children');
- for (var i = 0, length = children.length; i < length; i++) {
- var child = children[i];
- if (child.get('visible')) {
- var box = child.getBBox();
- if (!box) {
- continue;
- }
- var leftTop = [box.minX, box.minY];
- var leftBottom = [box.minX, box.maxY];
- var rightTop = [box.maxX, box.minY];
- var rightBottom = [box.maxX, box.maxY];
- var matrix = child.attr('matrix');
- _vector["default"].transformMat2d(leftTop, leftTop, matrix);
- _vector["default"].transformMat2d(leftBottom, leftBottom, matrix);
- _vector["default"].transformMat2d(rightTop, rightTop, matrix);
- _vector["default"].transformMat2d(rightBottom, rightBottom, matrix);
- minX = Math.min(leftTop[0], leftBottom[0], rightTop[0], rightBottom[0], minX);
- maxX = Math.max(leftTop[0], leftBottom[0], rightTop[0], rightBottom[0], maxX);
- minY = Math.min(leftTop[1], leftBottom[1], rightTop[1], rightBottom[1], minY);
- maxY = Math.max(leftTop[1], leftBottom[1], rightTop[1], rightBottom[1], maxY);
- }
- }
- return {
- minX: minX,
- minY: minY,
- maxX: maxX,
- maxY: maxY,
- x: minX,
- y: minY,
- width: maxX - minX,
- height: maxY - minY
- };
- };
- _proto.destroy = function destroy() {
- if (this.get('destroyed')) {
- return;
- }
- this.clear();
- _Element.prototype.destroy.call(this);
- };
- return Group;
- }(_element["default"]);
- (0, common.mix)(Group.prototype, _container["default"], {
- getGroupClass: function getGroupClass() {
- return Group;
- }
- });
- var _default = Group;
- exports["default"] = _default;
- });
- unwrapExports(group$2);
- var requestAnimationFrame_1 = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.requestAnimationFrame = void 0;
- var requestAnimationFrame = typeof window === 'object' && window.requestAnimationFrame ? window.requestAnimationFrame : function (fn) {
- return setTimeout(fn, 16);
- };
- exports.requestAnimationFrame = requestAnimationFrame;
- });
- unwrapExports(requestAnimationFrame_1);
- var requestAnimationFrame_2 = requestAnimationFrame_1.requestAnimationFrame;
- var canvas = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _emit = _interopRequireDefault(emit);
- var _controller = _interopRequireDefault(controller);
- var _canvasElement = _interopRequireDefault(canvasElement);
- var _container = _interopRequireDefault(container);
- var _group = _interopRequireDefault(group$2);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Canvas = /*#__PURE__*/function (_EventEmit) {
- _inheritsLoose(Canvas, _EventEmit);
- var _proto = Canvas.prototype;
- _proto.get = function get(name) {
- return this._attrs[name];
- };
- _proto.set = function set(name, value) {
- this._attrs[name] = value;
- };
- function Canvas(cfg) {
- var _this;
- _this = _EventEmit.call(this) || this;
- _this._attrs = (0, common.mix)({
- type: 'canvas',
- children: []
- }, cfg);
- _this._initPixelRatio();
- _this._initCanvas();
- return _this;
- }
- _proto._initPixelRatio = function _initPixelRatio() {
- var pixelRatio = this.get('pixelRatio');
- if (!pixelRatio) {
- this.set('pixelRatio', (0, common.getPixelRatio)());
- }
- };
- _proto.beforeDraw = function beforeDraw() {
- var context = this._attrs.context;
- var el = this._attrs.el;
- context && context.clearRect && context.clearRect(0, 0, el.width, el.height);
- };
- _proto._initCanvas = function _initCanvas() {
- var self = this;
- var el = self.get('el');
- var context = self.get('context');
- if (!el && !context) {
- throw new Error('Please specify the id, el or context of the chart!');
- }
- var canvas;
- if (el) {
- // DOMElement or String
- canvas = (0, common.isString)(el) ? (0, common.getDomById)(el) : el;
- } else {
- // 说明没有指定el
- canvas = _canvasElement["default"].create(context);
- }
- if (context && canvas && !canvas.getContext) {
- canvas.getContext = function () {
- return context;
- };
- }
- var width = self.get('width');
- if (!width) {
- width = (0, common.getWidth)(canvas);
- }
- var height = self.get('height');
- if (!height) {
- height = (0, common.getHeight)(canvas);
- }
- self.set('canvas', this);
- self.set('el', canvas);
- self.set('context', context || canvas.getContext('2d'));
- self.changeSize(width, height); // 初始化事件控制器
- var eventController = new _controller["default"]({
- canvas: this,
- el: canvas
- });
- self.set('eventController', eventController);
- };
- _proto.changeSize = function changeSize(width, height) {
- var pixelRatio = this.get('pixelRatio');
- var canvasDOM = this.get('el'); // HTMLCanvasElement or canvasElement
- // 浏览器环境设置style样式
- if (canvasDOM.style) {
- canvasDOM.style.width = width + 'px';
- canvasDOM.style.height = height + 'px';
- }
- if ((0, common.isCanvasElement)(canvasDOM)) {
- canvasDOM.width = width * pixelRatio;
- canvasDOM.height = height * pixelRatio;
- if (pixelRatio !== 1) {
- var ctx = this.get('context');
- ctx.scale(pixelRatio, pixelRatio);
- }
- }
- this.set('width', width);
- this.set('height', height);
- };
- _proto.getWidth = function getWidth() {
- var pixelRatio = this.get('pixelRatio');
- var width = this.get('width');
- return width * pixelRatio;
- };
- _proto.getHeight = function getHeight() {
- var pixelRatio = this.get('pixelRatio');
- var height = this.get('height');
- return height * pixelRatio;
- };
- _proto.getPointByClient = function getPointByClient(clientX, clientY) {
- var el = this.get('el');
- var bbox = el.getBoundingClientRect();
- var width = bbox.right - bbox.left;
- var height = bbox.bottom - bbox.top;
- return {
- x: (clientX - bbox.left) * (el.width / width),
- y: (clientY - bbox.top) * (el.height / height)
- };
- };
- _proto._beginDraw = function _beginDraw() {
- this._attrs.toDraw = true;
- };
- _proto._endDraw = function _endDraw() {
- this._attrs.toDraw = false;
- };
- _proto.draw = function draw() {
- var self = this;
- function drawInner() {
- self.set('animateHandler', (0, requestAnimationFrame_1.requestAnimationFrame)(function () {
- self.set('animateHandler', undefined);
- if (self.get('toDraw')) {
- drawInner();
- }
- }));
- self.beforeDraw();
- try {
- var context = self._attrs.context;
- self.drawInner(context); // 支付宝,微信小程序,需要调context.draw才能完成绘制, 所以这里直接判断是否有.draw方法
- if (context.draw) {
- context.draw();
- }
- } catch (ev) {
- console.warn('error in draw canvas, detail as:');
- console.warn(ev);
- self._endDraw();
- }
- self._endDraw();
- }
- if (self.get('destroyed')) {
- return;
- }
- if (self.get('animateHandler')) {
- this._beginDraw();
- } else {
- drawInner();
- }
- };
- _proto.destroy = function destroy() {
- if (this.get('destroyed')) {
- return;
- } // 需要清理 canvas 画布内容,否则会导致 spa 应用 ios 下 canvas 白屏
- // https://stackoverflow.com/questions/52532614/total-canvas-memory-use-exceeds-the-maximum-limit-safari-12
- // https://github.com/antvis/F2/issues/630
- var el = this.get('el');
- el.width = 0;
- el.height = 0;
- this.clear();
- this._attrs = {};
- this.set('destroyed', true);
- };
- _proto.isDestroyed = function isDestroyed() {
- return this.get('destroyed');
- };
- return Canvas;
- }(_emit["default"]);
- (0, common.mix)(Canvas.prototype, _container["default"], {
- getGroupClass: function getGroupClass() {
- return _group["default"];
- }
- });
- var _default = Canvas;
- exports["default"] = _default;
- });
- unwrapExports(canvas);
- var rect = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- // 为了处理radius 大于 width 或 height 的场景
- function parseRadius(radius, width, height) {
- radius = (0, common.parsePadding)(radius); // 都为0
- if (!radius[0] && !radius[1] && !radius[2] && !radius[3]) {
- return radius;
- }
- var minWidth = Math.max(radius[0] + radius[1], radius[2] + radius[3]);
- var minHeight = Math.max(radius[0] + radius[3], radius[1] + radius[2]);
- var scale = Math.min(width / minWidth, height / minHeight);
- if (scale < 1) {
- return radius.map(function (r) {
- return r * scale;
- });
- }
- return radius;
- }
- var Rect = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Rect, _Shape);
- function Rect() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Rect.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'rect';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- radius: 0,
- lineWidth: 0
- };
- };
- _proto.createPath = function createPath(context) {
- var self = this;
- var attrs = self.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- width = attrs.width,
- height = attrs.height,
- radius = attrs.radius;
- context.beginPath();
- if (!radius || !(width * height)) {
- context.rect(x, y, width, height);
- } else {
- radius = parseRadius(radius, width, height);
- context.moveTo(x + radius[0], y);
- context.lineTo(x + width - radius[1], y);
- context.arc(x + width - radius[1], y + radius[1], radius[1], -Math.PI / 2, 0, false);
- context.lineTo(x + width, y + height - radius[2]);
- context.arc(x + width - radius[2], y + height - radius[2], radius[2], 0, Math.PI / 2, false);
- context.lineTo(x + radius[3], y + height);
- context.arc(x + radius[3], y + height - radius[3], radius[3], Math.PI / 2, Math.PI, false);
- context.lineTo(x, y + radius[0]);
- context.arc(x + radius[0], y + radius[0], radius[0], Math.PI, Math.PI * 3 / 2, false);
- context.closePath();
- }
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- width = attrs.width,
- height = attrs.height;
- return {
- minX: x,
- minY: y,
- maxX: x + width,
- maxY: y + height
- };
- };
- return Rect;
- }(_shape["default"]);
- _shape["default"].Rect = Rect;
- var _default = Rect;
- exports["default"] = _default;
- });
- unwrapExports(rect);
- var image = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var ImageShape = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(ImageShape, _Shape);
- function ImageShape() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = ImageShape.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = false;
- this._attrs.canStroke = false;
- this._attrs.loading = false;
- this._attrs.image = null;
- this._attrs.type = 'image';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- width: 0,
- height: 0
- };
- };
- _proto.createPath = function createPath(context) {
- var _this = this;
- var attrs = this.get('attrs');
- var src = attrs.src;
- if (this.get('loading')) {
- return;
- }
- var image = this.get('image');
- if (image) {
- this.drawImage(context, image);
- } else {
- if (src && Image) {
- this.set('loading', true);
- var _image = new Image();
- _image.src = src; // 设置跨域
- _image.crossOrigin = 'Anonymous';
- _image.onload = function () {
- _this.set('loading', false);
- _this.set('image', _image);
- _this.drawImage(context, _image);
- };
- }
- }
- };
- _proto.drawImage = function drawImage(context, image) {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- width = attrs.width,
- height = attrs.height,
- sx = attrs.sx,
- sy = attrs.sy,
- swidth = attrs.swidth,
- sheight = attrs.sheight;
- if (!(0, common.isNil)(sx) && !(0, common.isNil)(sy) && !(0, common.isNil)(swidth) && !(0, common.isNil)(sheight)) {
- context.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
- } else {
- context.drawImage(image, x, y, width, height);
- }
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- width = attrs.width,
- height = attrs.height; // 和rect一样
- return {
- minX: x,
- minY: y,
- maxX: x + width,
- maxY: y + height
- };
- };
- return ImageShape;
- }(_shape["default"]);
- _shape["default"].Image = ImageShape;
- var _default = ImageShape;
- exports["default"] = _default;
- });
- unwrapExports(image);
- var circle = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Circle = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Circle, _Shape);
- function Circle() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Circle.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'circle';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- r: 0,
- lineWidth: 0
- };
- };
- _proto.createPath = function createPath(context) {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- r = attrs.r;
- context.beginPath();
- context.arc(x, y, r, 0, Math.PI * 2, false);
- context.closePath();
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- r = attrs.r;
- return {
- minX: x - r,
- maxX: x + r,
- minY: y - r,
- maxY: y + r
- };
- };
- return Circle;
- }(_shape["default"]);
- _shape["default"].Circle = Circle;
- var _default = Circle;
- exports["default"] = _default;
- });
- unwrapExports(circle);
- var bbox = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.getBBoxFromPoints = getBBoxFromPoints;
- exports.getBBoxFromLine = getBBoxFromLine;
- exports.getBBoxFromArc = getBBoxFromArc;
- exports.getBBoxFromBezierGroup = getBBoxFromBezierGroup;
- var _vector = _interopRequireDefault(vector2);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- var start = _vector["default"].create();
- var end = _vector["default"].create();
- var extremity = _vector["default"].create();
- function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
- var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
- var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
- return {
- x: x,
- y: y
- };
- } // cubic helper formula at T distance
- function CubicN(T, a, b, c, d) {
- var t2 = T * T;
- var t3 = t2 * T;
- return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
- }
- function cubicBezierBounds(c) {
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- var s = {
- x: c[0],
- y: c[1]
- };
- var c1 = {
- x: c[2],
- y: c[3]
- };
- var c2 = {
- x: c[4],
- y: c[5]
- };
- var e = {
- x: c[6],
- y: c[7]
- };
- for (var t = 0; t < 100; t++) {
- var pt = getCubicBezierXYatT(s, c1, c2, e, t / 100);
- if (pt.x < minX) {
- minX = pt.x;
- }
- if (pt.x > maxX) {
- maxX = pt.x;
- }
- if (pt.y < minY) {
- minY = pt.y;
- }
- if (pt.y > maxY) {
- maxY = pt.y;
- }
- }
- return {
- minX: minX,
- minY: minY,
- maxX: maxX,
- maxY: maxY
- };
- }
- function getBBoxFromPoints(points, lineWidth) {
- if (points.length === 0) {
- return;
- }
- var p = points[0];
- var left = p.x;
- var right = p.x;
- var top = p.y;
- var bottom = p.y;
- var len = points.length;
- for (var i = 1; i < len; i++) {
- p = points[i];
- left = Math.min(left, p.x);
- right = Math.max(right, p.x);
- top = Math.min(top, p.y);
- bottom = Math.max(bottom, p.y);
- }
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: left - lineWidth,
- minY: top - lineWidth,
- maxX: right + lineWidth,
- maxY: bottom + lineWidth
- };
- }
- function getBBoxFromLine(x0, y0, x1, y1, lineWidth) {
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: Math.min(x0, x1) - lineWidth,
- minY: Math.min(y0, y1) - lineWidth,
- maxX: Math.max(x0, x1) + lineWidth,
- maxY: Math.max(y0, y1) + lineWidth
- };
- }
- function getBBoxFromArc(x, y, r, startAngle, endAngle, anticlockwise) {
- var diff = Math.abs(startAngle - endAngle);
- if (diff % (Math.PI * 2) < 1e-4 && diff > 1e-4) {
- // Is a circle
- return {
- minX: x - r,
- minY: y - r,
- maxX: x + r,
- maxY: y + r
- };
- }
- start[0] = Math.cos(startAngle) * r + x;
- start[1] = Math.sin(startAngle) * r + y;
- end[0] = Math.cos(endAngle) * r + x;
- end[1] = Math.sin(endAngle) * r + y;
- var min = [0, 0];
- var max = [0, 0];
- _vector["default"].min(min, start, end);
- _vector["default"].max(max, start, end); // Thresh to [0, Math.PI * 2]
- startAngle = startAngle % (Math.PI * 2);
- if (startAngle < 0) {
- startAngle = startAngle + Math.PI * 2;
- }
- endAngle = endAngle % (Math.PI * 2);
- if (endAngle < 0) {
- endAngle = endAngle + Math.PI * 2;
- }
- if (startAngle > endAngle && !anticlockwise) {
- endAngle += Math.PI * 2;
- } else if (startAngle < endAngle && anticlockwise) {
- startAngle += Math.PI * 2;
- }
- if (anticlockwise) {
- var tmp = endAngle;
- endAngle = startAngle;
- startAngle = tmp;
- }
- for (var angle = 0; angle < endAngle; angle += Math.PI / 2) {
- if (angle > startAngle) {
- extremity[0] = Math.cos(angle) * r + x;
- extremity[1] = Math.sin(angle) * r + y;
- _vector["default"].min(min, extremity, min);
- _vector["default"].max(max, extremity, max);
- }
- }
- return {
- minX: min[0],
- minY: min[1],
- maxX: max[0],
- maxY: max[1]
- };
- }
- function getBBoxFromBezierGroup(points, lineWidth) {
- var minX = Infinity;
- var maxX = -Infinity;
- var minY = Infinity;
- var maxY = -Infinity;
- for (var i = 0, len = points.length; i < len; i++) {
- var bbox = cubicBezierBounds(points[i]);
- if (bbox.minX < minX) {
- minX = bbox.minX;
- }
- if (bbox.maxX > maxX) {
- maxX = bbox.maxX;
- }
- if (bbox.minY < minY) {
- minY = bbox.minY;
- }
- if (bbox.maxY > maxY) {
- maxY = bbox.maxY;
- }
- }
- lineWidth = lineWidth / 2 || 0;
- return {
- minX: minX - lineWidth,
- minY: minY - lineWidth,
- maxX: maxX + lineWidth,
- maxY: maxY + lineWidth
- };
- }
- });
- unwrapExports(bbox);
- var bbox_1 = bbox.getBBoxFromPoints;
- var bbox_2 = bbox.getBBoxFromLine;
- var bbox_3 = bbox.getBBoxFromArc;
- var bbox_4 = bbox.getBBoxFromBezierGroup;
- var line = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Line = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Line, _Shape);
- function Line() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Line.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canStroke = true;
- this._attrs.type = 'line';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- x1: 0,
- y1: 0,
- x2: 0,
- y2: 0,
- lineWidth: 1
- };
- };
- _proto.createPath = function createPath(context) {
- var attrs = this.get('attrs');
- var x1 = attrs.x1,
- y1 = attrs.y1,
- x2 = attrs.x2,
- y2 = attrs.y2;
- context.beginPath();
- context.moveTo(x1, y1);
- context.lineTo(x2, y2);
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var x1 = attrs.x1,
- y1 = attrs.y1,
- x2 = attrs.x2,
- y2 = attrs.y2,
- lineWidth = attrs.lineWidth;
- return (0, bbox.getBBoxFromLine)(x1, y1, x2, y2, lineWidth);
- };
- return Line;
- }(_shape["default"]);
- _shape["default"].Line = Line;
- var _default = Line;
- exports["default"] = _default;
- });
- unwrapExports(line);
- var polygon = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Polygon = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Polygon, _Shape);
- function Polygon() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Polygon.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'polygon';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- points: null,
- lineWidth: 0
- };
- };
- _proto.createPath = function createPath(context) {
- var self = this;
- var attrs = self.get('attrs');
- var points = attrs.points;
- context.beginPath();
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- if (i === 0) {
- context.moveTo(point.x, point.y);
- } else {
- context.lineTo(point.x, point.y);
- }
- }
- context.closePath();
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var points = attrs.points;
- return (0, bbox.getBBoxFromPoints)(points);
- };
- return Polygon;
- }(_shape["default"]);
- _shape["default"].Polygon = Polygon;
- var _default = Polygon;
- exports["default"] = _default;
- });
- unwrapExports(polygon);
- var smooth = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.smooth = catmullRom2bezier;
- var _vector = _interopRequireDefault(vector2);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- /**
- * @fileOverview convert the line to curve
- * @author dxq613@gmail.com
- */
- function getPoint(v) {
- return [v.x, v.y];
- }
- function smoothBezier(points, smooth, isLoop, constraint) {
- var cps = [];
- var prevPoint;
- var nextPoint;
- var hasConstraint = !!constraint;
- var min;
- var max;
- var point;
- var len;
- var l;
- var i;
- if (hasConstraint) {
- min = [Infinity, Infinity];
- max = [-Infinity, -Infinity];
- for (i = 0, l = points.length; i < l; i++) {
- point = getPoint(points[i]);
- _vector["default"].min(min, min, point);
- _vector["default"].max(max, max, point);
- }
- _vector["default"].min(min, min, constraint[0]);
- _vector["default"].max(max, max, constraint[1]);
- }
- for (i = 0, len = points.length; i < len; i++) {
- point = getPoint(points[i]);
- if (isLoop) {
- prevPoint = getPoint(points[i ? i - 1 : len - 1]);
- nextPoint = getPoint(points[(i + 1) % len]);
- } else {
- if (i === 0 || i === len - 1) {
- cps.push([point[0], point[1]]);
- continue;
- } else {
- prevPoint = getPoint(points[i - 1]);
- nextPoint = getPoint(points[i + 1]);
- }
- }
- var v = _vector["default"].sub([], nextPoint, prevPoint);
- _vector["default"].scale(v, v, smooth);
- var d0 = _vector["default"].distance(point, prevPoint);
- var d1 = _vector["default"].distance(point, nextPoint);
- var sum = d0 + d1;
- if (sum !== 0) {
- d0 /= sum;
- d1 /= sum;
- }
- var v1 = _vector["default"].scale([], v, -d0);
- var v2 = _vector["default"].scale([], v, d1);
- var cp0 = _vector["default"].add([], point, v1);
- var cp1 = _vector["default"].add([], point, v2);
- if (hasConstraint) {
- _vector["default"].max(cp0, cp0, min);
- _vector["default"].min(cp0, cp0, max);
- _vector["default"].max(cp1, cp1, min);
- _vector["default"].min(cp1, cp1, max);
- }
- cps.push([cp0[0], cp0[1]]);
- cps.push([cp1[0], cp1[1]]);
- }
- if (isLoop) {
- cps.push(cps.shift());
- }
- return cps;
- }
- function catmullRom2bezier(pointList, z, constraint) {
- var isLoop = !!z;
- var controlPointList = smoothBezier(pointList, 0.4, isLoop, constraint);
- var len = pointList.length;
- var d1 = [];
- var cp1;
- var cp2;
- var p;
- for (var i = 0; i < len - 1; i++) {
- cp1 = controlPointList[i * 2];
- cp2 = controlPointList[i * 2 + 1];
- p = pointList[i + 1];
- d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
- }
- if (isLoop) {
- cp1 = controlPointList[len];
- cp2 = controlPointList[len + 1];
- p = pointList[0];
- d1.push(['C', cp1[0], cp1[1], cp2[0], cp2[1], p.x, p.y]);
- }
- return d1;
- }
- });
- unwrapExports(smooth);
- var smooth_1 = smooth.smooth;
- var polyline = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- var Smooth = _interopRequireWildcard(smooth);
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- // filter the point which x or y is NaN
- function _filterPoints(points) {
- var filteredPoints = [];
- for (var i = 0, len = points.length; i < len; i++) {
- var point = points[i];
- if (!isNaN(point.x) && !isNaN(point.y)) {
- filteredPoints.push(point);
- }
- }
- return filteredPoints;
- }
- var Polyline = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Polyline, _Shape);
- function Polyline() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Polyline.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'polyline';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- points: null,
- lineWidth: 1,
- smooth: false
- };
- };
- _proto.createPath = function createPath(context) {
- var self = this;
- var attrs = self.get('attrs');
- var points = attrs.points,
- smooth = attrs.smooth;
- var filteredPoints = _filterPoints(points);
- context.beginPath();
- if (filteredPoints.length) {
- context.moveTo(filteredPoints[0].x, filteredPoints[0].y);
- if (smooth) {
- var constaint = [[0, 0], [1, 1]];
- var sps = Smooth.smooth(filteredPoints, false, constaint);
- for (var i = 0, n = sps.length; i < n; i++) {
- var sp = sps[i];
- context.bezierCurveTo(sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]);
- }
- } else {
- var _i;
- var l;
- for (_i = 1, l = filteredPoints.length - 1; _i < l; _i++) {
- context.lineTo(filteredPoints[_i].x, filteredPoints[_i].y);
- }
- context.lineTo(filteredPoints[l].x, filteredPoints[l].y);
- }
- }
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var points = attrs.points,
- smooth = attrs.smooth,
- lineWidth = attrs.lineWidth;
- var filteredPoints = _filterPoints(points);
- if (smooth) {
- var newPoints = [];
- var constaint = [[0, 0], [1, 1]];
- var sps = Smooth.smooth(filteredPoints, false, constaint);
- for (var i = 0, n = sps.length; i < n; i++) {
- var sp = sps[i];
- if (i === 0) {
- newPoints.push([filteredPoints[0].x, filteredPoints[0].y, sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
- } else {
- var lastPoint = sps[i - 1];
- newPoints.push([lastPoint[5], lastPoint[6], sp[1], sp[2], sp[3], sp[4], sp[5], sp[6]]);
- }
- }
- return (0, bbox.getBBoxFromBezierGroup)(newPoints, lineWidth);
- }
- return (0, bbox.getBBoxFromPoints)(filteredPoints, lineWidth);
- };
- return Polyline;
- }(_shape["default"]);
- _shape["default"].Polyline = Polyline;
- var _default = Polyline;
- exports["default"] = _default;
- });
- unwrapExports(polyline);
- var arc = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Arc = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Arc, _Shape);
- function Arc() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Arc.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canStroke = true;
- this._attrs.canFill = true;
- this._attrs.type = 'arc';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- r: 0,
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false,
- lineWidth: 1
- };
- };
- _proto.createPath = function createPath(context) {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- r = attrs.r,
- startAngle = attrs.startAngle,
- endAngle = attrs.endAngle,
- anticlockwise = attrs.anticlockwise;
- context.beginPath();
- if (startAngle !== endAngle) {
- context.arc(x, y, r, startAngle, endAngle, anticlockwise);
- }
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- r = attrs.r,
- startAngle = attrs.startAngle,
- endAngle = attrs.endAngle,
- anticlockwise = attrs.anticlockwise;
- return (0, bbox.getBBoxFromArc)(x, y, r, startAngle, endAngle, anticlockwise);
- };
- return Arc;
- }(_shape["default"]);
- _shape["default"].Arc = Arc;
- var _default = Arc;
- exports["default"] = _default;
- });
- unwrapExports(arc);
- var sector = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Sector = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Sector, _Shape);
- function Sector() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Sector.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'sector';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- x: 0,
- y: 0,
- lineWidth: 0,
- r: 0,
- r0: 0,
- startAngle: 0,
- endAngle: Math.PI * 2,
- anticlockwise: false
- };
- };
- _proto.createPath = function createPath(context) {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- startAngle = attrs.startAngle,
- endAngle = attrs.endAngle,
- r = attrs.r,
- r0 = attrs.r0,
- anticlockwise = attrs.anticlockwise;
- context.beginPath();
- var unitX = Math.cos(startAngle);
- var unitY = Math.sin(startAngle);
- context.moveTo(unitX * r0 + x, unitY * r0 + y);
- context.lineTo(unitX * r + x, unitY * r + y); // 当扇形的角度非常小的时候,就不进行弧线的绘制;或者整个只有1个扇形时,会出现end<0的情况不绘制
- if (Math.abs(endAngle - startAngle) > 0.0001 || startAngle === 0 && endAngle < 0) {
- context.arc(x, y, r, startAngle, endAngle, anticlockwise);
- context.lineTo(Math.cos(endAngle) * r0 + x, Math.sin(endAngle) * r0 + y);
- if (r0 !== 0) {
- context.arc(x, y, r0, endAngle, startAngle, !anticlockwise);
- }
- }
- context.closePath();
- };
- _proto.calculateBox = function calculateBox() {
- var attrs = this.get('attrs');
- var x = attrs.x,
- y = attrs.y,
- r = attrs.r,
- r0 = attrs.r0,
- startAngle = attrs.startAngle,
- endAngle = attrs.endAngle,
- anticlockwise = attrs.anticlockwise;
- var outerBBox = (0, bbox.getBBoxFromArc)(x, y, r, startAngle, endAngle, anticlockwise);
- var innerBBox = (0, bbox.getBBoxFromArc)(x, y, r0, startAngle, endAngle, anticlockwise);
- return {
- minX: Math.min(outerBBox.minX, innerBBox.minX),
- minY: Math.min(outerBBox.minY, innerBBox.minY),
- maxX: Math.max(outerBBox.maxX, innerBBox.maxX),
- maxY: Math.max(outerBBox.maxY, innerBBox.maxY)
- };
- };
- return Sector;
- }(_shape["default"]);
- _shape["default"].Sector = Sector;
- var _default = Sector;
- exports["default"] = _default;
- });
- unwrapExports(sector);
- var rect$1 = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var Rect = {
- calcRotatedBox: function calcRotatedBox(_ref) {
- var width = _ref.width,
- height = _ref.height,
- rotate = _ref.rotate;
- var absRotate = Math.abs(rotate);
- return {
- width: Math.abs(width * Math.cos(absRotate) + height * Math.sin(absRotate)),
- height: Math.abs(height * Math.cos(absRotate) + width * Math.sin(absRotate))
- };
- }
- };
- var _default = Rect;
- exports["default"] = _default;
- });
- unwrapExports(rect$1);
- var text = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- var _rect = _interopRequireDefault(rect$1);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var textWidthCacheCounter = 0;
- var textWidthCache = {};
- var TEXT_CACHE_MAX = 5000;
- var Text = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Text, _Shape);
- function Text() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Text.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.type = 'text';
- };
- _proto.getDefaultAttrs = function getDefaultAttrs() {
- return {
- lineWidth: 0,
- lineCount: 1,
- fontSize: 12,
- fontFamily: 'sans-serif',
- fontStyle: 'normal',
- fontWeight: 'normal',
- fontVariant: 'normal',
- textAlign: 'start',
- textBaseline: 'bottom',
- lineHeight: null,
- textArr: null
- };
- };
- _proto._getFontStyle = function _getFontStyle() {
- var attrs = this._attrs.attrs;
- var fontSize = attrs.fontSize,
- fontFamily = attrs.fontFamily,
- fontWeight = attrs.fontWeight,
- fontStyle = attrs.fontStyle,
- fontVariant = attrs.fontVariant;
- return fontStyle + " " + fontVariant + " " + fontWeight + " " + fontSize + "px " + fontFamily;
- };
- _proto._afterAttrsSet = function _afterAttrsSet() {
- var attrs = this._attrs.attrs;
- attrs.font = this._getFontStyle();
- if (attrs.text) {
- var text = attrs.text;
- var textArr = null;
- var lineCount = 1;
- if ((0, common.isString)(text) && text.indexOf('\n') !== -1) {
- textArr = text.split('\n');
- lineCount = textArr.length;
- }
- attrs.lineCount = lineCount;
- attrs.textArr = textArr;
- }
- this.set('attrs', attrs);
- };
- _proto._getTextHeight = function _getTextHeight() {
- var attrs = this._attrs.attrs;
- if (attrs.height) {
- return attrs.height;
- }
- var lineCount = attrs.lineCount;
- var fontSize = attrs.fontSize * 1;
- if (lineCount > 1) {
- var spaceingY = this._getSpaceingY();
- return fontSize * lineCount + spaceingY * (lineCount - 1);
- }
- return fontSize;
- };
- _proto._getSpaceingY = function _getSpaceingY() {
- var attrs = this._attrs.attrs;
- var lineHeight = attrs.lineHeight;
- var fontSize = attrs.fontSize * 1;
- return lineHeight ? lineHeight - fontSize : fontSize * 0.14;
- };
- _proto.drawInner = function drawInner(context) {
- var self = this;
- var attrs = self._attrs.attrs;
- var text = attrs.text;
- var x = attrs.x;
- var y = attrs.y;
- if ((0, common.isNil)(text) || isNaN(x) || isNaN(y)) {
- // text will be 0
- return;
- }
- var textArr = attrs.textArr;
- var fontSize = attrs.fontSize * 1;
- var spaceingY = self._getSpaceingY();
- if (attrs.rotate) {
- // do rotation
- context.translate(x, y);
- context.rotate(attrs.rotate);
- x = 0;
- y = 0;
- }
- var textBaseline = attrs.textBaseline;
- var height;
- if (textArr) {
- height = self._getTextHeight();
- }
- var subY; // context.beginPath();
- if (self.hasFill()) {
- var fillOpacity = attrs.fillOpacity;
- if (!(0, common.isNil)(fillOpacity) && fillOpacity !== 1) {
- context.globalAlpha = fillOpacity;
- }
- if (textArr) {
- for (var i = 0, len = textArr.length; i < len; i++) {
- var subText = textArr[i];
- subY = y + i * (spaceingY + fontSize) - height + fontSize; // bottom;
- if (textBaseline === 'middle') {
- subY += height - fontSize - (height - fontSize) / 2;
- }
- if (textBaseline === 'top') {
- subY += height - fontSize;
- }
- context.fillText(subText, x, subY);
- }
- } else {
- context.fillText(text, x, y);
- }
- }
- if (self.hasStroke()) {
- if (textArr) {
- for (var _i = 0, _len = textArr.length; _i < _len; _i++) {
- var _subText = textArr[_i];
- subY = y + _i * (spaceingY + fontSize) - height + fontSize; // bottom;
- if (textBaseline === 'middle') {
- subY += height - fontSize - (height - fontSize) / 2;
- }
- if (textBaseline === 'top') {
- subY += height - fontSize;
- }
- context.strokeText(_subText, x, subY);
- }
- } else {
- context.strokeText(text, x, y);
- }
- }
- };
- _proto.calculateBox = function calculateBox() {
- var self = this;
- var attrs = self._attrs.attrs;
- var x = attrs.x,
- y = attrs.y,
- textAlign = attrs.textAlign,
- textBaseline = attrs.textBaseline;
- var width = self._getTextWidth(); // attrs.width
- if (!width) {
- return {
- minX: x,
- minY: y,
- maxX: x,
- maxY: y
- };
- }
- var height = self._getTextHeight(); // attrs.height
- if (attrs.rotate) {
- var rotatedBox = _rect["default"].calcRotatedBox({
- width: width,
- height: height,
- rotate: attrs.rotate
- });
- width = rotatedBox.width;
- height = rotatedBox.height;
- }
- var point = {
- x: x,
- y: y - height
- }; // default textAlign: start, textBaseline: bottom
- if (textAlign) {
- if (textAlign === 'end' || textAlign === 'right') {
- point.x -= width;
- } else if (textAlign === 'center') {
- point.x -= width / 2;
- }
- }
- if (textBaseline) {
- if (textBaseline === 'top') {
- point.y += height;
- } else if (textBaseline === 'middle') {
- point.y += height / 2;
- }
- }
- return {
- minX: point.x,
- minY: point.y,
- maxX: point.x + width,
- maxY: point.y + height
- };
- };
- _proto._getTextWidth = function _getTextWidth() {
- var attrs = this._attrs.attrs;
- if (attrs.width) {
- return attrs.width;
- }
- var text = attrs.text;
- var context = this.get('context');
- if ((0, common.isNil)(text)) return undefined;
- var font = attrs.font;
- var textArr = attrs.textArr;
- var key = text + '' + font;
- if (textWidthCache[key]) {
- return textWidthCache[key];
- }
- var width = 0;
- if (textArr) {
- for (var i = 0, length = textArr.length; i < length; i++) {
- var subText = textArr[i];
- width = Math.max(width, (0, common.measureText)(subText, font, context).width);
- }
- } else {
- width = (0, common.measureText)(text, font, context).width;
- }
- if (textWidthCacheCounter > TEXT_CACHE_MAX) {
- textWidthCacheCounter = 0;
- textWidthCache = {};
- }
- textWidthCacheCounter++;
- textWidthCache[key] = width;
- return width;
- };
- return Text;
- }(_shape["default"]);
- _shape["default"].Text = Text;
- var _default = Text;
- exports["default"] = _default;
- });
- unwrapExports(text);
- var custom = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports["default"] = void 0;
- var _shape = _interopRequireDefault(shape);
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
- var Custom = /*#__PURE__*/function (_Shape) {
- _inheritsLoose(Custom, _Shape);
- function Custom() {
- return _Shape.apply(this, arguments) || this;
- }
- var _proto = Custom.prototype;
- _proto._initProperties = function _initProperties() {
- _Shape.prototype._initProperties.call(this);
- this._attrs.canFill = true;
- this._attrs.canStroke = true;
- this._attrs.createPath = null;
- this._attrs.type = 'custom';
- };
- _proto.createPath = function createPath(context) {
- var createPath = this.get('createPath');
- createPath && createPath.call(this, context);
- };
- _proto.calculateBox = function calculateBox() {
- var calculateBox = this.get('calculateBox');
- return calculateBox && calculateBox.call(this);
- };
- return Custom;
- }(_shape["default"]);
- _shape["default"].Custom = Custom;
- var _default = Custom;
- exports["default"] = _default;
- });
- unwrapExports(custom);
- var graphic = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- var _canvas = _interopRequireDefault(canvas);
- exports.Canvas = _canvas["default"];
- var _group = _interopRequireDefault(group$2);
- exports.Group = _group["default"];
- var _shape = _interopRequireDefault(shape);
- exports.Shape = _shape["default"];
- var _matrix = _interopRequireDefault(matrix);
- exports.Matrix = _matrix["default"];
- var _vector = _interopRequireDefault(vector2);
- exports.Vector2 = _vector["default"];
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
- });
- unwrapExports(graphic);
- var graphic_1 = graphic.Canvas;
- var graphic_2 = graphic.Group;
- var graphic_3 = graphic.Shape;
- var graphic_4 = graphic.Matrix;
- var graphic_5 = graphic.Vector2;
- var pieLabel = createCommonjsModule(function (module, exports) {
- exports.__esModule = true;
- exports.init = init;
- exports.afterGeomDraw = afterGeomDraw;
- exports.clearInner = clearInner;
- exports["default"] = void 0;
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
- var DEFAULT_CFG = {
- anchorOffset: 5,
- // 锚点的偏移量
- inflectionOffset: 15,
- // 拐点的偏移量
- sidePadding: 20,
- // 文本距离画布四边的距离
- lineHeight: 32,
- // 文本的行高
- adjustOffset: 15,
- // 发生调整时的偏移量
- skipOverlapLabels: false,
- // 是否不展示重叠的文本
- triggerOn: 'touchstart',
- // 点击行为触发的时间类型
- activeShape: false,
- // 当有图形被选中的时候,是否激活图形
- activeStyle: {
- offset: 1,
- appendRadius: 8,
- fillOpacity: 0.5
- },
- label1OffsetY: -1,
- label2OffsetY: 1
- };
- function getEndPoint(center, angle, r) {
- return {
- x: center.x + r * Math.cos(angle),
- y: center.y + r * Math.sin(angle)
- };
- } // 计算中间角度
- function getMiddleAngle(startAngle, endAngle) {
- if (endAngle < startAngle) {
- endAngle += Math.PI * 2;
- }
- return (endAngle + startAngle) / 2;
- } // 判断两个矩形是否相交
- function isOverlap(label1, label2) {
- var label1BBox = label1.getBBox();
- var label2BBox = label2.getBBox();
- return Math.max(label1BBox.minX, label2BBox.minX) <= Math.min(label1BBox.maxX, label2BBox.maxX) && Math.max(label1BBox.minY, label2BBox.minY) <= Math.min(label1BBox.maxY, label2BBox.maxY);
- }
- var controller = /*#__PURE__*/function () {
- function controller(cfg) {
- var _this = this;
- _defineProperty(this, "_handleEvent", function (ev) {
- var self = _this;
- var chart = self.chart,
- drawnLabels = self.drawnLabels,
- pieLabelCfg = self.pieLabelCfg;
- var onClick = pieLabelCfg.onClick,
- activeShape = pieLabelCfg.activeShape;
- var canvasEvent = (0, common.createEvent)(ev, chart);
- var x = canvasEvent.x,
- y = canvasEvent.y; // 查找被点击的 label
- var clickedShape;
- for (var i = 0, len = drawnLabels.length; i < len; i++) {
- var shape = drawnLabels[i];
- var bbox = shape.getBBox(); // 通过最小包围盒来判断击中情况
- if (x >= bbox.minX && x <= bbox.maxX && y >= bbox.minY && y <= bbox.maxY) {
- clickedShape = shape;
- break;
- }
- }
- var pieData = chart.getSnapRecords({
- x: x,
- y: y
- });
- if (clickedShape) {
- canvasEvent.data = clickedShape.get('data');
- } else if (pieData.length) {
- // 击中饼图扇形区域
- canvasEvent.data = pieData[0]._origin;
- }
- onClick && onClick(canvasEvent);
- canvasEvent.data && activeShape && _this._activeShape(canvasEvent.data);
- });
- (0, common.mix)(this, cfg);
- var _chart = this.chart;
- this.canvasDom = _chart.get('canvas').get('el');
- }
- var _proto = controller.prototype;
- _proto.renderLabels = function renderLabels() {
- var self = this;
- var chart = self.chart,
- pieLabelCfg = self.pieLabelCfg,
- labelGroup = self.labelGroup;
- var halves = [[], // left
- [] // right
- ]; // 存储左右 labels
- var geom = chart.get('geoms')[0];
- var shapes = geom.get('container').get('children');
- var anchorOffset = pieLabelCfg.anchorOffset,
- inflectionOffset = pieLabelCfg.inflectionOffset,
- label1 = pieLabelCfg.label1,
- label2 = pieLabelCfg.label2,
- lineHeight = pieLabelCfg.lineHeight,
- skipOverlapLabels = pieLabelCfg.skipOverlapLabels,
- label1OffsetY = pieLabelCfg.label1OffsetY,
- label2OffsetY = pieLabelCfg.label2OffsetY;
- var coord = chart.get('coord');
- var center = coord.center,
- radius = coord.circleRadius;
- shapes.forEach(function (shape) {
- var _shape$_attrs$attrs = shape._attrs.attrs,
- startAngle = _shape$_attrs$attrs.startAngle,
- endAngle = _shape$_attrs$attrs.endAngle;
- var middleAngle = getMiddleAngle(startAngle, endAngle);
- var anchorPoint = getEndPoint(center, middleAngle, radius + anchorOffset);
- var inflectionPoint = getEndPoint(center, middleAngle, radius + inflectionOffset);
- var origin = shape.get('origin');
- var _origin = origin._origin,
- color = origin.color;
- var label = {
- _anchor: anchorPoint,
- _inflection: inflectionPoint,
- _data: _origin,
- x: inflectionPoint.x,
- y: inflectionPoint.y,
- r: radius + inflectionOffset,
- fill: color
- };
- var textGroup = new graphic.Group({
- context: chart.get('canvas').get('context'),
- // 兼容 node、小程序环境
- data: _origin // 存储原始数据
- });
- var textAttrs = {
- x: 0,
- y: 0,
- fontSize: 12,
- lineHeight: 12,
- fill: '#808080'
- };
- if ((0, common.isFunction)(label1)) {
- textGroup.addShape('Text', {
- attrs: (0, common.mix)({
- textBaseline: 'bottom'
- }, textAttrs, label1(_origin, color)),
- data: _origin,
- // 存储原始数据
- offsetY: label1OffsetY
- });
- }
- if ((0, common.isFunction)(label2)) {
- textGroup.addShape('Text', {
- attrs: (0, common.mix)({
- textBaseline: 'top'
- }, textAttrs, label2(_origin, color)),
- data: _origin,
- // 存储原始数据
- offsetY: label2OffsetY
- });
- }
- label.textGroup = textGroup; // 判断文本的方向
- if (anchorPoint.x < center.x) {
- label._side = 'left';
- halves[0].push(label);
- } else {
- label._side = 'right';
- halves[1].push(label);
- }
- });
- var drawnLabels = [];
- if (skipOverlapLabels) {
- var lastLabel; // 存储上一个 label 对象,用于检测文本是否重叠
- var labels = halves[1].concat(halves[0]); // 顺时针
- for (var i = 0, len = labels.length; i < len; i++) {
- var label = labels[i];
- var textGroup = self._drawLabel(label);
- if (lastLabel) {
- if (isOverlap(textGroup, lastLabel)) {
- // 重叠了就不绘制
- continue;
- }
- }
- labelGroup.add(textGroup);
- self._drawLabelLine(label);
- lastLabel = textGroup;
- drawnLabels.push(textGroup);
- }
- } else {
- var height = chart.get('height');
- var maxCountForOneSide = parseInt(height / lineHeight, 10);
- halves.forEach(function (half) {
- if (half.length > maxCountForOneSide) {
- half.splice(maxCountForOneSide, half.length - maxCountForOneSide);
- }
- half.sort(function (a, b) {
- return a.y - b.y;
- });
- var labels = self._antiCollision(half);
- drawnLabels = drawnLabels.concat(labels);
- });
- }
- this.drawnLabels = drawnLabels;
- };
- _proto.bindEvents = function bindEvents() {
- var pieLabelCfg = this.pieLabelCfg;
- var triggerOn = pieLabelCfg.triggerOn || 'touchstart';
- (0, common.addEventListener)(this.canvasDom, triggerOn, this._handleEvent);
- };
- _proto.unBindEvents = function unBindEvents() {
- var pieLabelCfg = this.pieLabelCfg;
- var triggerOn = pieLabelCfg.triggerOn || 'touchstart';
- (0, common.removeEventListener)(this.canvasDom, triggerOn, this._handleEvent);
- };
- _proto.clear = function clear() {
- this.labelGroup && this.labelGroup.clear();
- this.halo && this.halo.remove(true);
- this.lastSelectedData = null;
- this.drawnLabels = [];
- this.unBindEvents();
- };
- _proto._drawLabel = function _drawLabel(label) {
- var pieLabelCfg = this.pieLabelCfg,
- chart = this.chart;
- var canvasWidth = chart.get('width');
- var sidePadding = pieLabelCfg.sidePadding;
- var y = label.y,
- textGroup = label.textGroup;
- var children = textGroup.get('children');
- var textAttrs = {
- textAlign: label._side === 'left' ? 'left' : 'right',
- x: label._side === 'left' ? sidePadding : canvasWidth - sidePadding
- };
- children.forEach(function (child) {
- child.attr(textAttrs);
- child.attr('y', y + child.get('offsetY'));
- });
- return textGroup;
- };
- _proto._drawLabelLine = function _drawLabelLine(label, maxLabelWidth) {
- var chart = this.chart,
- pieLabelCfg = this.pieLabelCfg,
- labelGroup = this.labelGroup;
- var canvasWidth = chart.get('width');
- var sidePadding = pieLabelCfg.sidePadding,
- adjustOffset = pieLabelCfg.adjustOffset,
- lineStyle = pieLabelCfg.lineStyle,
- anchorStyle = pieLabelCfg.anchorStyle,
- skipOverlapLabels = pieLabelCfg.skipOverlapLabels;
- var _anchor = label._anchor,
- _inflection = label._inflection,
- fill = label.fill,
- y = label.y;
- var lastPoint = {
- x: label._side === 'left' ? sidePadding : canvasWidth - sidePadding,
- y: y
- };
- var points = [_anchor, _inflection, lastPoint];
- if (!skipOverlapLabels && _inflection.y !== y) {
- // 展示全部文本文本位置做过调整
- if (_inflection.y < y) {
- // 文本被调整下去了,则添加拐点连接线
- var point1 = _inflection;
- var point2 = {
- x: label._side === 'left' ? lastPoint.x + maxLabelWidth + adjustOffset : lastPoint.x - maxLabelWidth - adjustOffset,
- y: _inflection.y
- };
- var point3 = {
- x: label._side === 'left' ? lastPoint.x + maxLabelWidth : lastPoint.x - maxLabelWidth,
- y: lastPoint.y
- };
- points = [_anchor, point1, point2, point3, lastPoint];
- if (label._side === 'right' && point2.x < point1.x || label._side === 'left' && point2.x > point1.x) {
- points = [_anchor, point3, lastPoint];
- }
- } else {
- points = [_anchor, {
- x: _inflection.x,
- y: y
- }, lastPoint];
- }
- }
- labelGroup.addShape('Polyline', {
- attrs: (0, common.mix)({
- points: points,
- lineWidth: 1,
- stroke: fill
- }, lineStyle)
- }); // 绘制锚点
- labelGroup.addShape('Circle', {
- attrs: (0, common.mix)({
- x: _anchor.x,
- y: _anchor.y,
- r: 2,
- fill: fill
- }, anchorStyle)
- });
- };
- _proto._antiCollision = function _antiCollision(half) {
- var self = this;
- var chart = self.chart,
- pieLabelCfg = self.pieLabelCfg;
- var coord = chart.get('coord');
- var canvasHeight = chart.get('height');
- var center = coord.center,
- r = coord.circleRadius;
- var inflectionOffset = pieLabelCfg.inflectionOffset,
- lineHeight = pieLabelCfg.lineHeight;
- var startY = center.y - r - inflectionOffset - lineHeight;
- var overlapping = true;
- var totalH = canvasHeight;
- var i;
- var maxY = 0;
- var minY = Number.MIN_VALUE;
- var maxLabelWidth = 0;
- var boxes = half.map(function (label) {
- var labelY = label.y;
- if (labelY > maxY) {
- maxY = labelY;
- }
- if (labelY < minY) {
- minY = labelY;
- }
- var textGroup = label.textGroup;
- var labelWidth = textGroup.getBBox().width;
- if (labelWidth >= maxLabelWidth) {
- maxLabelWidth = labelWidth;
- }
- return {
- size: lineHeight,
- targets: [labelY - startY]
- };
- });
- if (maxY - startY > totalH) {
- totalH = maxY - startY;
- }
- var iteratorBoxed = function iteratorBoxed(boxes) {
- boxes.forEach(function (box) {
- var target = (Math.min.apply(minY, box.targets) + Math.max.apply(minY, box.targets)) / 2;
- box.pos = Math.min(Math.max(minY, target - box.size / 2), totalH - box.size);
- });
- };
- while (overlapping) {
- iteratorBoxed(boxes); // detect overlapping and join boxes
- overlapping = false;
- i = boxes.length;
- while (i--) {
- if (i > 0) {
- var previousBox = boxes[i - 1];
- var box = boxes[i];
- if (previousBox.pos + previousBox.size > box.pos) {
- // overlapping
- previousBox.size += box.size;
- previousBox.targets = previousBox.targets.concat(box.targets); // overflow, shift up
- if (previousBox.pos + previousBox.size > totalH) {
- previousBox.pos = totalH - previousBox.size;
- }
- boxes.splice(i, 1); // removing box
- overlapping = true;
- }
- }
- }
- }
- i = 0;
- boxes.forEach(function (b) {
- var posInCompositeBox = startY; // middle of the label
- b.targets.forEach(function () {
- half[i].y = b.pos + posInCompositeBox + lineHeight / 2;
- posInCompositeBox += lineHeight;
- i++;
- });
- });
- var drawnLabels = [];
- half.forEach(function (label) {
- var textGroup = self._drawLabel(label);
- var labelGroup = self.labelGroup;
- labelGroup.add(textGroup);
- self._drawLabelLine(label, maxLabelWidth);
- drawnLabels.push(textGroup);
- });
- return drawnLabels;
- };
- _proto._getSelectedShapeByData = function _getSelectedShapeByData(data) {
- var selectedShape = null;
- var chart = this.chart;
- var geom = chart.get('geoms')[0];
- var container = geom.get('container');
- var children = container.get('children');
- (0, common.each)(children, function (child) {
- if (child.get('isShape') && child.get('className') === geom.get('type')) {
- // get geometry's shape
- var shapeData = child.get('origin')._origin;
- if ((0, common.isObjectValueEqual)(shapeData, data)) {
- selectedShape = child;
- return false;
- }
- }
- });
- return selectedShape;
- };
- _proto._activeShape = function _activeShape(data) {
- var chart = this.chart,
- lastSelectedData = this.lastSelectedData,
- pieLabelCfg = this.pieLabelCfg;
- if (data === lastSelectedData) {
- return;
- }
- this.lastSelectedData = data;
- var activeStyle = pieLabelCfg.activeStyle;
- var selectedShape = this._getSelectedShapeByData(data);
- var _selectedShape$_attrs = selectedShape._attrs.attrs,
- x = _selectedShape$_attrs.x,
- y = _selectedShape$_attrs.y,
- startAngle = _selectedShape$_attrs.startAngle,
- endAngle = _selectedShape$_attrs.endAngle,
- r = _selectedShape$_attrs.r,
- fill = _selectedShape$_attrs.fill;
- var frontPlot = chart.get('frontPlot');
- this.halo && this.halo.remove(true);
- var halo = frontPlot.addShape('sector', {
- attrs: (0, common.mix)({
- x: x,
- y: y,
- r: r + activeStyle.offset + activeStyle.appendRadius,
- r0: r + activeStyle.offset,
- fill: fill,
- startAngle: startAngle,
- endAngle: endAngle
- }, activeStyle)
- });
- this.halo = halo;
- chart.get('canvas').draw();
- };
- return controller;
- }();
- function init(chart) {
- var frontPlot = chart.get('frontPlot');
- var labelGroup = frontPlot.addGroup({
- className: 'pie-label',
- zIndex: 0
- });
- var pieLabelController = new controller({
- chart: chart,
- labelGroup: labelGroup
- });
- chart.set('pieLabelController', pieLabelController);
- chart.pieLabel = function (cfg) {
- cfg = (0, common.deepMix)({}, DEFAULT_CFG, cfg);
- pieLabelController.pieLabelCfg = cfg;
- return this;
- };
- }
- function afterGeomDraw(chart) {
- var controller = chart.get('pieLabelController');
- if (controller.pieLabelCfg) {
- // 用户配置了饼图文本
- controller.renderLabels();
- controller.bindEvents(); // 绑定事件
- }
- }
- function clearInner(chart) {
- var controller = chart.get('pieLabelController');
- if (controller.pieLabelCfg) {
- // 用户配置了饼图文本
- controller.clear();
- }
- }
- var _default = {
- init: init,
- afterGeomDraw: afterGeomDraw,
- clearInner: clearInner
- };
- exports["default"] = _default;
- });
- var PieLabel = unwrapExports(pieLabel);
- var pieLabel_1 = pieLabel.init;
- var pieLabel_2 = pieLabel.afterGeomDraw;
- var pieLabel_3 = pieLabel.clearInner;
- F2.Chart.plugins.register(PieLabel);
- function wrapEvent(e) {
- if (!e) return;
- if (!e.preventDefault) {
- e.preventDefault = function() {};
- }
- return e;
- }
- Component({
- /**
- * 组件的属性列表
- */
- properties: {
- onInit: {
- type: 'Function',
- value: () => {}
- }
- },
- /**
- * 组件的初始数据
- */
- data: {
- },
- ready() {
- const query = wx.createSelectorQuery().in(this);
- query.select('.f2-canvas')
- .fields({
- node: true,
- size: true
- })
- .exec(res => {
- const { node, width, height } = res[0];
- const context = node.getContext('2d');
- const pixelRatio = wx.getSystemInfoSync().pixelRatio;
- // 高清设置
- node.width = width * pixelRatio;
- node.height = height * pixelRatio;
- const config = { context, width, height, pixelRatio };
- const chart = this.data.onInit(F2, config);
- if (chart) {
- this.chart = chart;
- this.canvasEl = chart.get('el');
- }
- });
- },
- /**
- * 组件的方法列表
- */
- methods: {
- touchStart(e) {
- const canvasEl = this.canvasEl;
- if (!canvasEl) {
- return;
- }
- canvasEl.dispatchEvent('touchstart', wrapEvent(e));
- },
- touchMove(e) {
- const canvasEl = this.canvasEl;
- if (!canvasEl) {
- return;
- }
- canvasEl.dispatchEvent('touchmove', wrapEvent(e));
- },
- touchEnd(e) {
- const canvasEl = this.canvasEl;
- if (!canvasEl) {
- return;
- }
- canvasEl.dispatchEvent('touchend', wrapEvent(e));
- }
- }
- });
- })));
|