PPT.vue 180 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094
  1. <!--
  2. * @Author: LiZhiWei
  3. * @Date: 2025-04-10 14:38:27
  4. * @LastEditors: LiZhiWei
  5. * @LastEditTime: 2025-04-29 10:32:14
  6. * @Description:
  7. -->
  8. <template>
  9. <div id="pptx-container" ref="pptxContainer" class="pptx-container"></div>
  10. </template>
  11. <script>
  12. export default {
  13. name: "PPT",
  14. props: {
  15. pptxJson: Object,
  16. },
  17. data() {
  18. return {}
  19. },
  20. mounted() {
  21. this.renderSlides()
  22. },
  23. computed: {},
  24. watch: {
  25. pptxJson: {
  26. handler() {
  27. this.renderSlides()
  28. },
  29. deep: true,
  30. },
  31. },
  32. methods: {
  33. renderSlides() {
  34. if (!this.$refs.pptxContainer || !this.pptxJson) return
  35. this.$refs.pptxContainer.innerHTML = ""
  36. const { size, slides } = this.pptxJson
  37. slides.forEach((slide, index) => {
  38. const slideElement = this.createSlideElement(size.width, size.height)
  39. this.applySlideBackground(slideElement, slide.fill)
  40. if (slide.layoutElements && Array.isArray(slide.layoutElements)) {
  41. this.processElements(slide.layoutElements, index + 1)
  42. slide.layoutElements.forEach((element) => {
  43. const el = this.createElementByType(element)
  44. if (!el) return
  45. slideElement.appendChild(el)
  46. })
  47. }
  48. // 渲染幻灯片元素
  49. if (slide.elements && Array.isArray(slide.elements)) {
  50. this.processElements(slide.elements, index + 1)
  51. slide.elements.forEach((element) => {
  52. const el = this.createElementByType(element)
  53. if (!el) return
  54. slideElement.appendChild(el)
  55. })
  56. }
  57. // 添加幻灯片到容器
  58. this.$refs.pptxContainer.appendChild(slideElement)
  59. })
  60. // 为所有p标签应用样式
  61. const pTags = this.$refs.pptxContainer.querySelectorAll("p")
  62. pTags.forEach((p) => {
  63. p.style.margin = "0px"
  64. p.style.padding = "0px"
  65. p.style.wordBreak = "break-word"
  66. p.style.lineHeight = "1"
  67. })
  68. const ulTags = this.$refs.pptxContainer.querySelectorAll("ul")
  69. ulTags.forEach((ul) => {
  70. ul.style.wordBreak = "break-word"
  71. ul.style.lineHeight = "1"
  72. ul.style.padding = "auto 0px"
  73. ul.style.margin = "0px"
  74. })
  75. const olTags = this.$refs.pptxContainer.querySelectorAll("ol")
  76. olTags.forEach((ol) => {
  77. ol.style.margin = "0px"
  78. ol.style.padding = "auto 0px"
  79. ol.style.wordBreak = "break-word"
  80. ol.style.lineHeight = "1"
  81. })
  82. },
  83. // 创建幻灯片元素
  84. createSlideElement(width, height) {
  85. const slideElement = document.createElement("div")
  86. slideElement.className = "slide"
  87. slideElement.style.position = "relative"
  88. slideElement.style.width = width + "px"
  89. slideElement.style.height = height + "px"
  90. slideElement.style.border = "1px solid #ccc"
  91. slideElement.style.margin = "0px auto"
  92. slideElement.style.marginBottom = "20px"
  93. slideElement.style.overflow = "hidden"
  94. return slideElement
  95. },
  96. // 应用幻灯片背景
  97. applySlideBackground(slideElement, fill) {
  98. if (!fill) return
  99. if (fill.type === "gradient") {
  100. const { colors, path, rot } = fill.value
  101. if (colors && colors.length >= 2) {
  102. const gradientType = path === "rect" ? "linear" : "radial"
  103. const gradientAngle =
  104. gradientType === "linear" ? (90 - (rot || 0)) % 360 : rot || 0
  105. let gradientString = `${gradientType}-gradient(`
  106. if (gradientType === "linear") {
  107. gradientString += `${gradientAngle}deg, `
  108. }
  109. colors.forEach((color, i) => {
  110. gradientString += `${color.color} ${color.pos}${
  111. i < colors.length - 1 ? ", " : ""
  112. }`
  113. })
  114. gradientString += ")"
  115. slideElement.style.background = gradientString
  116. }
  117. } else if (fill.type === "color") {
  118. slideElement.style.backgroundColor = fill.value || "#FFFFFF"
  119. } else if (fill.type === "image" && fill.value.picBase64) {
  120. // 设置背景图片
  121. slideElement.style.backgroundImage = `url(${fill.value.picBase64})`
  122. slideElement.style.backgroundSize = "cover"
  123. slideElement.style.backgroundPosition = "center"
  124. slideElement.style.backgroundRepeat = "no-repeat"
  125. // 如果有背景图片的混合模式
  126. if (fill.value.blendMode) {
  127. slideElement.style.backgroundBlendMode = fill.value.blendMode
  128. }
  129. // 如果有透明度设置
  130. if (fill.value.opacity !== undefined) {
  131. slideElement.style.opacity = fill.value.opacity
  132. }
  133. }
  134. },
  135. // 根据元素类型创建DOM元素
  136. createElementByType(element) {
  137. switch (element.type) {
  138. case "image":
  139. return this.createImageElement(element)
  140. case "video":
  141. return this.createVideoElement(element)
  142. case "audio":
  143. return this.createAudioElement(element)
  144. case "shape":
  145. return this.createShapeElement(element)
  146. case "table":
  147. return this.createTableElement(element)
  148. case "chart":
  149. return this.createChartElement(element)
  150. case "diagram":
  151. return this.createDiagramElement(element)
  152. case "math":
  153. return this.createMathElement(element)
  154. case "group":
  155. return this.createGroupElement(element)
  156. default:
  157. return this.createTextElement(element)
  158. }
  159. },
  160. createGroupElement(element) {
  161. // 创建组合容器
  162. const groupContainer = document.createElement("div")
  163. groupContainer.className = "group-element"
  164. groupContainer.style.position = "absolute"
  165. groupContainer.style.top = element.top + "px"
  166. groupContainer.style.left = element.left + "px"
  167. groupContainer.style.width = element.width + "px"
  168. groupContainer.style.height = element.height + "px"
  169. groupContainer.style.zIndex = element.order
  170. groupContainer.style.transformOrigin = "center center"
  171. // 创建内部容器来处理子元素
  172. const innerContainer = document.createElement("div")
  173. innerContainer.style.position = "relative"
  174. innerContainer.style.width = "100%"
  175. innerContainer.style.height = "100%"
  176. // 应用旋转变换
  177. if (element.rotate) {
  178. groupContainer.style.transform = `rotate(${element.rotate}deg)`
  179. }
  180. // 应用其他样式属性
  181. if (element.opacity !== undefined) {
  182. groupContainer.style.opacity = element.opacity
  183. }
  184. // 递归渲染组内的所有子元素
  185. if (element.elements && Array.isArray(element.elements)) {
  186. element.elements.forEach((childElement) => {
  187. const childCopy = JSON.parse(JSON.stringify(childElement))
  188. const childEl = this.createElementByType(childCopy)
  189. if (childEl) {
  190. innerContainer.appendChild(childEl)
  191. }
  192. })
  193. }
  194. groupContainer.appendChild(innerContainer)
  195. return groupContainer
  196. },
  197. // 递归调整元素位置
  198. adjustElementPosition(element, parentElement) {
  199. // 创建深拷贝,但保留特殊属性的引用
  200. const adjustedElement = JSON.parse(JSON.stringify(element))
  201. // 调整位置为相对于父组合元素的位置
  202. adjustedElement.top = element.top - parentElement.top
  203. adjustedElement.left = element.left - parentElement.left
  204. // 恢复特殊属性的引用
  205. const specialProps = [
  206. "src",
  207. "blob",
  208. "fill",
  209. "text",
  210. "path",
  211. "elements",
  212. "borderColor",
  213. "borderWidth",
  214. "borderType",
  215. ]
  216. specialProps.forEach((prop) => {
  217. if (element[prop] !== undefined) {
  218. adjustedElement[prop] = element[prop]
  219. }
  220. })
  221. // 如果是组合元素,递归处理其子元素
  222. if (element.type === "group" && element.elements) {
  223. adjustedElement.elements = element.elements.map((childElement) =>
  224. this.adjustElementPosition(childElement, {
  225. top: element.top,
  226. left: element.left,
  227. })
  228. )
  229. }
  230. return adjustedElement
  231. },
  232. // 创建图像元素
  233. createImageElement(element) {
  234. const img = document.createElement("img")
  235. img.src = element.src
  236. img.style.width = element.width + "px"
  237. img.style.height = element.height + "px"
  238. img.style.objectFit = "cover" // 保持图像的宽高比并填充容器
  239. img.style.position = "absolute"
  240. img.style.top = `${element.top}px`
  241. img.style.left = `${element.left}px`
  242. img.style.zIndex = element.order
  243. return img
  244. },
  245. // 创建视频元素
  246. createVideoElement(element) {
  247. const el = document.createElement("video")
  248. el.src = element.blob
  249. el.controls = true
  250. el.style.width = element.width + "px"
  251. el.style.height = element.height + "px"
  252. el.style.position = "absolute"
  253. el.style.top = element.top + "px"
  254. el.style.left = element.left + "px"
  255. el.style.zIndex = element.order
  256. return el
  257. },
  258. // 创建音频元素
  259. createAudioElement(element) {
  260. const el = document.createElement("audio")
  261. el.src = element.blob
  262. el.controls = true
  263. el.style.height = element.height + "px"
  264. el.style.position = "absolute"
  265. el.style.top = element.top + "px"
  266. el.style.left = element.left + "px"
  267. el.style.zIndex = element.order
  268. return el
  269. },
  270. // 创建形状元素
  271. createShapeElement(element) {
  272. const el = document.createElement("div")
  273. el.style.position = "absolute"
  274. el.style.top = element.top + "px"
  275. el.style.left = element.left + "px"
  276. el.style.width = element.width + "px"
  277. el.style.height = element.height + "px"
  278. el.style.zIndex = element.order
  279. el.style.overflow = "visible"
  280. if (element.height === 0) {
  281. // 如果高度为0,直接在div上绘制边框
  282. el.style.borderTop = `${element.borderWidth || 1}px ${
  283. element.borderType || "solid"
  284. } ${element.borderColor || "#000"}`
  285. }
  286. // 使用SVG绘制形状
  287. const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
  288. svg.setAttribute("width", "100%")
  289. svg.setAttribute("height", "100%")
  290. svg.setAttribute("viewBox", `0 0 ${element.width} ${element.height}`)
  291. svg.style.overflow = "visible"
  292. const setBackground = (element, shape) => {
  293. if (element.fill && element.fill.type) {
  294. // 设置填充色
  295. if (element.fill.type === "color") {
  296. shape.setAttribute("fill", element.fill.value || "transparent")
  297. } else if (element.fill.type === "gradient") {
  298. // 渐变填充
  299. const { colors, path, rot } = element.fill.value
  300. if (colors && colors.length >= 2) {
  301. const gradientType = path === "rect" ? "linear" : "radial"
  302. const gradientAngle =
  303. gradientType === "linear" ? (90 - (rot || 0)) % 360 : rot || 0
  304. let gradientString = `${gradientType}-gradient(`
  305. if (gradientType === "linear") {
  306. gradientString += `${gradientAngle}deg, `
  307. }
  308. colors.forEach((color, i) => {
  309. gradientString += `${color.color} ${color.pos}${
  310. i < colors.length - 1 ? ", " : ""
  311. }`
  312. })
  313. gradientString += ")"
  314. // 创建渐变定义
  315. const gradientDef = document.createElementNS(
  316. "http://www.w3.org/2000/svg",
  317. "defs"
  318. )
  319. const gradientEl = document.createElementNS(
  320. "http://www.w3.org/2000/svg",
  321. gradientType === "linear" ? "linearGradient" : "radialGradient"
  322. )
  323. const gradientId = `gradient-${Date.now()}-${Math.random()
  324. .toString(36)
  325. .substr(2, 9)}`
  326. gradientEl.setAttribute("id", gradientId)
  327. // 设置渐变属性
  328. if (gradientType === "linear") {
  329. gradientEl.setAttribute(
  330. "gradientTransform",
  331. `rotate(${gradientAngle})`
  332. )
  333. }
  334. // 添加渐变色标
  335. colors.forEach((color) => {
  336. const stop = document.createElementNS(
  337. "http://www.w3.org/2000/svg",
  338. "stop"
  339. )
  340. stop.setAttribute("offset", color.pos)
  341. stop.setAttribute("stop-color", color.color)
  342. gradientEl.appendChild(stop)
  343. })
  344. gradientDef.appendChild(gradientEl)
  345. svg.appendChild(gradientDef)
  346. // 应用渐变
  347. shape.setAttribute("fill", `url(#${gradientId})`)
  348. }
  349. } else if (element.fill.type === "image") {
  350. // 创建图案填充
  351. const pattern = document.createElementNS(
  352. "http://www.w3.org/2000/svg",
  353. "pattern"
  354. )
  355. const patternId = `pattern-${Date.now()}-${Math.random()
  356. .toString(36)
  357. .substr(2, 9)}`
  358. pattern.setAttribute("id", patternId)
  359. pattern.setAttribute("patternUnits", "userSpaceOnUse")
  360. pattern.setAttribute("width", "100%")
  361. pattern.setAttribute("height", "100%")
  362. // 创建图片元素
  363. const image = document.createElementNS(
  364. "http://www.w3.org/2000/svg",
  365. "image"
  366. )
  367. image.setAttribute("width", "100%")
  368. image.setAttribute("height", "100%")
  369. image.setAttribute("preserveAspectRatio", "xMidYMid slice")
  370. image.setAttributeNS(
  371. "http://www.w3.org/1999/xlink",
  372. "href",
  373. element.fill.value.picBase64
  374. )
  375. pattern.appendChild(image)
  376. // 添加pattern到defs
  377. const defs = document.createElementNS(
  378. "http://www.w3.org/2000/svg",
  379. "defs"
  380. )
  381. defs.appendChild(pattern)
  382. svg.appendChild(defs)
  383. // 应用图案填充
  384. shape.setAttribute("fill", `url(#${patternId})`)
  385. } else {
  386. shape.setAttribute("fill", "transparent")
  387. }
  388. } else {
  389. shape.setAttribute("fill", "#ffffff00")
  390. }
  391. }
  392. // 根据形状类型创建不同的SVG元素
  393. switch (element.shapType) {
  394. case "roundRect":
  395. const radius = Math.min(element.width, element.height) * 0.1
  396. const roundRect = document.createElementNS(
  397. "http://www.w3.org/2000/svg",
  398. "rect"
  399. )
  400. roundRect.setAttribute("x", 0)
  401. roundRect.setAttribute("y", 0)
  402. roundRect.setAttribute("width", element.width)
  403. roundRect.setAttribute("height", element.height)
  404. roundRect.setAttribute("rx", radius)
  405. roundRect.setAttribute("ry", radius)
  406. // 设置填充色
  407. setBackground(element, roundRect)
  408. // 设置边框
  409. if (element.borderWidth > 0) {
  410. roundRect.setAttribute("stroke", element.borderColor || "#000")
  411. roundRect.setAttribute("stroke-width", element.borderWidth || 1)
  412. roundRect.setAttribute("stroke-linejoin", "round") // 设置连接处为圆角
  413. roundRect.setAttribute("vector-effect", "non-scaling-stroke") // 防止边框宽度变形
  414. roundRect.setAttribute("shape-rendering", "geometricPrecision") // 提高渲染精度
  415. // 处理虚线边框
  416. if (
  417. element.borderType === "dotted" ||
  418. element.borderType === "dashed"
  419. ) {
  420. if (element.borderStrokeDasharray) {
  421. roundRect.setAttribute(
  422. "stroke-dasharray",
  423. element.borderStrokeDasharray
  424. )
  425. } else if (element.borderType === "dotted") {
  426. roundRect.setAttribute("stroke-dasharray", "1, 3")
  427. } else if (element.borderType === "dashed") {
  428. roundRect.setAttribute("stroke-dasharray", "5, 5")
  429. }
  430. }
  431. }
  432. svg.appendChild(roundRect)
  433. break
  434. case "snip1Rect":
  435. // 使用path元素绘制剪去单角的矩形
  436. const snip1Rect = document.createElementNS(
  437. "http://www.w3.org/2000/svg",
  438. "path"
  439. )
  440. // 计算剪角的大小,通常为矩形较短边的20%
  441. const snipSize = Math.min(element.width, element.height) * 0.35
  442. // 绘制路径:从左上角开始,顺时针方向,右上角被剪去
  443. snip1Rect.setAttribute(
  444. "d",
  445. `M0,0 ` +
  446. `L${element.width - snipSize},0 ` +
  447. `L${element.width},${snipSize} ` +
  448. `L${element.width},${element.height} ` +
  449. `L0,${element.height} ` +
  450. `Z`
  451. )
  452. // 设置填充色
  453. setBackground(element, snip1Rect)
  454. // 设置边框
  455. if (element.borderWidth > 0) {
  456. snip1Rect.setAttribute("stroke", element.borderColor || "#000")
  457. snip1Rect.setAttribute("stroke-width", element.borderWidth || 1)
  458. // 处理虚线边框
  459. if (
  460. element.borderType === "dotted" ||
  461. element.borderType === "dashed"
  462. ) {
  463. if (element.borderStrokeDasharray) {
  464. snip1Rect.setAttribute(
  465. "stroke-dasharray",
  466. element.borderStrokeDasharray
  467. )
  468. } else if (element.borderType === "dotted") {
  469. snip1Rect.setAttribute("stroke-dasharray", "1, 3")
  470. } else if (element.borderType === "dashed") {
  471. snip1Rect.setAttribute("stroke-dasharray", "5, 5")
  472. }
  473. }
  474. }
  475. svg.appendChild(snip1Rect)
  476. break
  477. case "snip2SameRect":
  478. // 使用path元素绘制剪去四个角的矩形
  479. const snip2SameRect = document.createElementNS(
  480. "http://www.w3.org/2000/svg",
  481. "path"
  482. )
  483. // 计算剪角的大小,通常为矩形较短边的20%
  484. const snip2Size = Math.min(element.width, element.height) * 0.35
  485. // 绘制路径:从左上角开始,顺时针方向,剪去四个角
  486. snip2SameRect.setAttribute(
  487. "d",
  488. `M${snip2Size},0 ` +
  489. `L${element.width - snip2Size},0 ` +
  490. `L${element.width},${snip2Size} ` +
  491. `L${element.width},${element.height - snip2Size} ` +
  492. `L${element.width - snip2Size},${element.height} ` +
  493. `L${snip2Size},${element.height} ` +
  494. `L0,${element.height - snip2Size} ` +
  495. `L0,${snip2Size} ` +
  496. `Z`
  497. )
  498. // 设置填充色
  499. setBackground(element, snip2SameRect)
  500. // 设置边框
  501. if (element.borderWidth > 0) {
  502. snip2SameRect.setAttribute("stroke", element.borderColor || "#000")
  503. snip2SameRect.setAttribute("stroke-width", element.borderWidth || 1)
  504. // 处理虚线边框
  505. if (
  506. element.borderType === "dotted" ||
  507. element.borderType === "dashed"
  508. ) {
  509. if (element.borderStrokeDasharray) {
  510. snip2SameRect.setAttribute(
  511. "stroke-dasharray",
  512. element.borderStrokeDasharray
  513. )
  514. } else if (element.borderType === "dotted") {
  515. snip2SameRect.setAttribute("stroke-dasharray", "2, 2")
  516. snip2SameRect.setAttribute("stroke-linecap", "round")
  517. } else if (element.borderType === "dashed") {
  518. snip2SameRect.setAttribute("stroke-dasharray", "6, 3")
  519. }
  520. }
  521. // 添加这些属性以确保边框正确渲染
  522. snip2SameRect.setAttribute("vector-effect", "non-scaling-stroke")
  523. snip2SameRect.setAttribute("shape-rendering", "geometricPrecision")
  524. }
  525. svg.appendChild(snip2SameRect)
  526. break
  527. case "line":
  528. // 创建直线连接符
  529. const line = document.createElementNS(
  530. "http://www.w3.org/2000/svg",
  531. "line"
  532. )
  533. // 设置SVG的最小高度为1px
  534. const svgHeight = element.height > 0 ? element.height : 1
  535. svg.setAttribute("height", svgHeight + "px")
  536. // 设置线条的起点和终点
  537. line.setAttribute("x1", 0)
  538. line.setAttribute("y1", 0)
  539. line.setAttribute("x2", element.width)
  540. line.setAttribute("y2", svgHeight)
  541. // 确保边框颜色和宽度被正确设置
  542. line.setAttribute("stroke", element.borderColor || "#000")
  543. line.setAttribute("stroke-width", element.borderWidth || 1)
  544. // 处理虚线样式
  545. if (
  546. element.borderType === "dotted" ||
  547. element.borderType === "dashed"
  548. ) {
  549. if (element.borderStrokeDasharray) {
  550. line.setAttribute(
  551. "stroke-dasharray",
  552. element.borderStrokeDasharray
  553. )
  554. } else if (element.borderType === "dotted") {
  555. line.setAttribute("stroke-dasharray", "2, 2")
  556. line.setAttribute("stroke-linecap", "round") // 添加圆角端点使点线更明显
  557. } else if (element.borderType === "dashed") {
  558. line.setAttribute("stroke-dasharray", "6, 3")
  559. }
  560. }
  561. // 确保线条正确渲染
  562. line.setAttribute("vector-effect", "non-scaling-stroke") // 防止缩放影响线条宽度
  563. svg.appendChild(line)
  564. break
  565. case "snip2DiagRect":
  566. // 使用path元素绘制剪去右上角和左下角的矩形
  567. const snip2DiagRect = document.createElementNS(
  568. "http://www.w3.org/2000/svg",
  569. "path"
  570. )
  571. // 计算剪角的大小,通常为矩形较短边的35%
  572. const snipDiagSize = Math.min(element.width, element.height) * 0.35
  573. // 绘制路径:从左上角开始,顺时针方向,右上角和左下角被剪去
  574. snip2DiagRect.setAttribute(
  575. "d",
  576. `M0,0 ` +
  577. `L${element.width - snipDiagSize},0 ` +
  578. `L${element.width},${snipDiagSize} ` +
  579. `L${element.width},${element.height} ` +
  580. `L${snipDiagSize},${element.height} ` +
  581. `L0,${element.height - snipDiagSize} ` +
  582. `Z`
  583. )
  584. // 设置填充色
  585. setBackground(element, snip2DiagRect)
  586. // 设置边框
  587. if (element.borderWidth > 0) {
  588. snip2DiagRect.setAttribute("stroke", element.borderColor || "#000")
  589. snip2DiagRect.setAttribute("stroke-width", element.borderWidth || 1)
  590. // 处理虚线边框
  591. if (
  592. element.borderType === "dotted" ||
  593. element.borderType === "dashed"
  594. ) {
  595. if (element.borderStrokeDasharray) {
  596. snip2DiagRect.setAttribute(
  597. "stroke-dasharray",
  598. element.borderStrokeDasharray
  599. )
  600. } else if (element.borderType === "dotted") {
  601. snip2DiagRect.setAttribute("stroke-dasharray", "2, 2")
  602. snip2DiagRect.setAttribute("stroke-linecap", "round")
  603. } else if (element.borderType === "dashed") {
  604. snip2DiagRect.setAttribute("stroke-dasharray", "6, 3")
  605. }
  606. }
  607. // 添加这些属性以确保边框正确渲染
  608. snip2DiagRect.setAttribute("vector-effect", "non-scaling-stroke")
  609. snip2DiagRect.setAttribute("shape-rendering", "geometricPrecision")
  610. }
  611. svg.appendChild(snip2DiagRect)
  612. break
  613. case "snipRoundRect":
  614. const snipRoundRect = document.createElementNS(
  615. "http://www.w3.org/2000/svg",
  616. "path"
  617. )
  618. // 计算剪切大小和圆角大小
  619. const snipSize2 = Math.min(element.width, element.height) * 0.4
  620. const roundSize = Math.min(element.width, element.height) * 0.5
  621. // 绘制路径:从左上角开始,顺时针方向,左上为圆角,右上为剪切角
  622. snipRoundRect.setAttribute(
  623. "d",
  624. `M${roundSize},0 ` +
  625. `L${element.width - snipSize2},0 ` +
  626. `L${element.width},${snipSize2} ` +
  627. `L${element.width},${element.height} ` +
  628. `L0,${element.height} ` +
  629. `L0,${roundSize} ` +
  630. `A${roundSize},${roundSize} 0 0,1 ${roundSize},0 ` +
  631. `Z`
  632. )
  633. // 设置填充色
  634. setBackground(element, snipRoundRect)
  635. // 设置边框
  636. if (element.borderWidth > 0) {
  637. snipRoundRect.setAttribute("stroke", element.borderColor || "#000")
  638. snipRoundRect.setAttribute("stroke-width", element.borderWidth || 1)
  639. // 处理虚线边框
  640. if (
  641. element.borderType === "dotted" ||
  642. element.borderType === "dashed"
  643. ) {
  644. if (element.borderStrokeDasharray) {
  645. snipRoundRect.setAttribute(
  646. "stroke-dasharray",
  647. element.borderStrokeDasharray
  648. )
  649. } else if (element.borderType === "dotted") {
  650. snipRoundRect.setAttribute("stroke-dasharray", "2, 2")
  651. snipRoundRect.setAttribute("stroke-linecap", "round")
  652. } else if (element.borderType === "dashed") {
  653. snipRoundRect.setAttribute("stroke-dasharray", "6, 3")
  654. }
  655. }
  656. snipRoundRect.setAttribute("vector-effect", "non-scaling-stroke")
  657. snipRoundRect.setAttribute("shape-rendering", "geometricPrecision")
  658. }
  659. svg.appendChild(snipRoundRect)
  660. break
  661. case "round1Rect":
  662. const round1Rect = document.createElementNS(
  663. "http://www.w3.org/2000/svg",
  664. "path"
  665. )
  666. // 计算圆角大小
  667. const round1Size = Math.min(element.width, element.height) * 0.5
  668. // 绘制路径:从左上角开始,顺时针方向,右上角为圆角
  669. round1Rect.setAttribute(
  670. "d",
  671. `M0,0 ` +
  672. `L${element.width - round1Size},0 ` +
  673. `Q${element.width},0 ${element.width},${round1Size} ` +
  674. `L${element.width},${element.height} ` +
  675. `L0,${element.height} ` +
  676. `Z`
  677. )
  678. // 设置填充色
  679. setBackground(element, round1Rect)
  680. // 设置边框
  681. if (element.borderWidth > 0) {
  682. round1Rect.setAttribute("stroke", element.borderColor || "#000")
  683. round1Rect.setAttribute("stroke-width", element.borderWidth || 1)
  684. // 处理虚线边框
  685. if (
  686. element.borderType === "dotted" ||
  687. element.borderType === "dashed"
  688. ) {
  689. if (element.borderStrokeDasharray) {
  690. round1Rect.setAttribute("stroke-dasharray", "40,15,5,15")
  691. } else if (element.borderType === "dotted") {
  692. round1Rect.setAttribute("stroke-dasharray", "2, 2")
  693. round1Rect.setAttribute("stroke-linecap", "round")
  694. } else if (element.borderType === "dashed") {
  695. round1Rect.setAttribute("stroke-dasharray", "6, 3")
  696. }
  697. }
  698. round1Rect.setAttribute("vector-effect", "non-scaling-stroke")
  699. round1Rect.setAttribute("shape-rendering", "geometricPrecision")
  700. }
  701. svg.appendChild(round1Rect)
  702. break
  703. case "ellipse":
  704. case "circle":
  705. const ellipse = document.createElementNS(
  706. "http://www.w3.org/2000/svg",
  707. "ellipse"
  708. )
  709. ellipse.setAttribute("cx", element.width / 2)
  710. ellipse.setAttribute("cy", element.height / 2)
  711. ellipse.setAttribute("rx", element.width / 2)
  712. ellipse.setAttribute("ry", element.height / 2)
  713. // 设置填充色
  714. setBackground(element, ellipse)
  715. // 设置边框
  716. if (element.borderWidth > 0) {
  717. ellipse.setAttribute("stroke", element.borderColor || "#000")
  718. ellipse.setAttribute("stroke-width", element.borderWidth || 1)
  719. // 处理虚线边框
  720. if (
  721. element.borderType === "dotted" ||
  722. element.borderType === "dashed"
  723. ) {
  724. if (element.borderStrokeDasharray) {
  725. ellipse.setAttribute(
  726. "stroke-dasharray",
  727. element.borderStrokeDasharray
  728. )
  729. } else if (element.borderType === "dotted") {
  730. ellipse.setAttribute("stroke-dasharray", "1, 3")
  731. } else if (element.borderType === "dashed") {
  732. ellipse.setAttribute("stroke-dasharray", "5, 5")
  733. }
  734. }
  735. }
  736. svg.appendChild(ellipse)
  737. break
  738. case "round2SameRect":
  739. const round2SameRect = document.createElementNS(
  740. "http://www.w3.org/2000/svg",
  741. "path"
  742. )
  743. // 计算圆角大小
  744. const round2Size = Math.min(element.width, element.height) * 0.5
  745. // 绘制路径:从左上角开始,顺时针方向,左上和右上为圆角
  746. round2SameRect.setAttribute(
  747. "d",
  748. `M${round2Size},0 ` +
  749. `L${element.width - round2Size},0 ` +
  750. `Q${element.width},0 ${element.width},${round2Size} ` +
  751. `L${element.width},${element.height} ` +
  752. `L0,${element.height} ` +
  753. `L0,${round2Size} ` +
  754. `Q0,0 ${round2Size},0 ` +
  755. `Z`
  756. )
  757. // 设置填充色
  758. setBackground(element, round2SameRect)
  759. // 设置边框
  760. if (element.borderWidth > 0) {
  761. round2SameRect.setAttribute("stroke", element.borderColor || "#000")
  762. round2SameRect.setAttribute(
  763. "stroke-width",
  764. element.borderWidth || 1
  765. )
  766. // 处理虚线边框
  767. if (
  768. element.borderType === "dotted" ||
  769. element.borderType === "dashed"
  770. ) {
  771. if (element.borderStrokeDasharray) {
  772. round2SameRect.setAttribute(
  773. "stroke-dasharray",
  774. element.borderStrokeDasharray
  775. )
  776. } else if (element.borderType === "dotted") {
  777. round2SameRect.setAttribute("stroke-dasharray", "2, 2")
  778. round2SameRect.setAttribute("stroke-linecap", "round")
  779. } else if (element.borderType === "dashed") {
  780. round2SameRect.setAttribute("stroke-dasharray", "6, 3")
  781. }
  782. }
  783. round2SameRect.setAttribute("vector-effect", "non-scaling-stroke")
  784. round2SameRect.setAttribute("shape-rendering", "geometricPrecision")
  785. }
  786. svg.appendChild(round2SameRect)
  787. break
  788. case "round2DiagRect":
  789. const round2DiagRect = document.createElementNS(
  790. "http://www.w3.org/2000/svg",
  791. "path"
  792. )
  793. // 计算圆角大小
  794. const round2DiagSize = Math.min(element.width, element.height) * 0.5
  795. // 绘制路径:从左上角开始,顺时针方向,左上和右下为圆角
  796. round2DiagRect.setAttribute(
  797. "d",
  798. `M${round2DiagSize},0 ` +
  799. `L${element.width},0 ` +
  800. `L${element.width},${element.height - round2DiagSize} ` +
  801. `Q${element.width},${element.height} ${
  802. element.width - round2DiagSize
  803. },${element.height} ` +
  804. `L0,${element.height} ` +
  805. `L0,${round2DiagSize} ` +
  806. `Q0,0 ${round2DiagSize},0 ` +
  807. `Z`
  808. )
  809. // 设置填充色
  810. setBackground(element, round2DiagRect)
  811. // 设置边框
  812. if (element.borderWidth > 0) {
  813. round2DiagRect.setAttribute("stroke", element.borderColor || "#000")
  814. round2DiagRect.setAttribute(
  815. "stroke-width",
  816. element.borderWidth || 1
  817. )
  818. // 处理虚线边框
  819. if (
  820. element.borderType === "dotted" ||
  821. element.borderType === "dashed"
  822. ) {
  823. if (element.borderStrokeDasharray) {
  824. round2DiagRect.setAttribute(
  825. "stroke-dasharray",
  826. element.borderStrokeDasharray
  827. )
  828. } else if (element.borderType === "dotted") {
  829. round2DiagRect.setAttribute("stroke-dasharray", "2, 2")
  830. round2DiagRect.setAttribute("stroke-linecap", "round")
  831. } else if (element.borderType === "dashed") {
  832. round2DiagRect.setAttribute("stroke-dasharray", "6, 3")
  833. }
  834. }
  835. round2DiagRect.setAttribute("vector-effect", "non-scaling-stroke")
  836. round2DiagRect.setAttribute("shape-rendering", "geometricPrecision")
  837. }
  838. svg.appendChild(round2DiagRect)
  839. break
  840. case "triangle":
  841. const triangle = document.createElementNS(
  842. "http://www.w3.org/2000/svg",
  843. "polygon"
  844. )
  845. triangle.setAttribute(
  846. "points",
  847. `${element.width / 2},0 ${element.width},${element.height} 0,${
  848. element.height
  849. }`
  850. )
  851. // 设置填充色
  852. setBackground(element, triangle)
  853. // 设置边框
  854. if (element.borderWidth > 0) {
  855. triangle.setAttribute("stroke", element.borderColor || "#000")
  856. triangle.setAttribute("stroke-width", element.borderWidth || 1)
  857. // 处理虚线边框
  858. if (
  859. element.borderType === "dotted" ||
  860. element.borderType === "dashed"
  861. ) {
  862. if (element.borderStrokeDasharray) {
  863. triangle.setAttribute(
  864. "stroke-dasharray",
  865. element.borderStrokeDasharray
  866. )
  867. } else if (element.borderType === "dotted") {
  868. triangle.setAttribute("stroke-dasharray", "1, 3")
  869. } else if (element.borderType === "dashed") {
  870. triangle.setAttribute("stroke-dasharray", "5, 5")
  871. }
  872. }
  873. }
  874. svg.appendChild(triangle)
  875. break
  876. case "arc":
  877. const arc = document.createElementNS(
  878. "http://www.w3.org/2000/svg",
  879. "path"
  880. )
  881. // 计算弧形的参数
  882. const arcRadius = Math.min(element.width, element.height) / 2
  883. // 绘制弧形路径
  884. arc.setAttribute(
  885. "d",
  886. `M${arcRadius},0 ` +
  887. `A${arcRadius},${arcRadius} 0 1 1 ${arcRadius * 0.15},${
  888. arcRadius * 0.5
  889. }`
  890. )
  891. // 设置填充色
  892. arc.setAttribute("fill", "transparent")
  893. // 设置边框
  894. if (element.borderWidth > 0) {
  895. arc.setAttribute("stroke", element.borderColor || "#000")
  896. arc.setAttribute("stroke-width", element.borderWidth || 0.5)
  897. // 处理虚线边框
  898. if (
  899. element.borderType === "dotted" ||
  900. element.borderType === "dashed"
  901. ) {
  902. if (element.borderStrokeDasharray) {
  903. arc.setAttribute(
  904. "stroke-dasharray",
  905. element.borderStrokeDasharray
  906. )
  907. } else if (element.borderType === "dotted") {
  908. arc.setAttribute("stroke-dasharray", "2, 2")
  909. arc.setAttribute("stroke-linecap", "round")
  910. } else if (element.borderType === "dashed") {
  911. arc.setAttribute("stroke-dasharray", "6, 3")
  912. }
  913. }
  914. arc.setAttribute("vector-effect", "non-scaling-stroke")
  915. arc.setAttribute("shape-rendering", "geometricPrecision")
  916. } else {
  917. arc.setAttribute("stroke", element.borderColor || "#000")
  918. arc.setAttribute("stroke-width", 0.5)
  919. }
  920. svg.appendChild(arc)
  921. break
  922. case "custom":
  923. const customPath = document.createElementNS(
  924. "http://www.w3.org/2000/svg",
  925. "path"
  926. )
  927. // 直接使用传入的 path 数据
  928. customPath.setAttribute("d", element.path || "")
  929. // 设置填充色
  930. setBackground(element, customPath)
  931. // 设置边框
  932. if (element.borderWidth > 0) {
  933. customPath.setAttribute("stroke", element.borderColor || "#000")
  934. customPath.setAttribute("stroke-width", element.borderWidth || 1)
  935. // 处理虚线边框
  936. if (
  937. element.borderType === "dotted" ||
  938. element.borderType === "dashed"
  939. ) {
  940. if (element.borderStrokeDasharray) {
  941. customPath.setAttribute(
  942. "stroke-dasharray",
  943. element.borderStrokeDasharray
  944. )
  945. } else if (element.borderType === "dotted") {
  946. customPath.setAttribute("stroke-dasharray", "2, 2")
  947. customPath.setAttribute("stroke-linecap", "round")
  948. } else if (element.borderType === "dashed") {
  949. customPath.setAttribute("stroke-dasharray", "6, 3")
  950. }
  951. }
  952. customPath.setAttribute("vector-effect", "non-scaling-stroke")
  953. customPath.setAttribute("shape-rendering", "geometricPrecision")
  954. }
  955. svg.appendChild(customPath)
  956. break
  957. case "teardrop":
  958. const teardrop = document.createElementNS(
  959. "http://www.w3.org/2000/svg",
  960. "path"
  961. )
  962. // 计算泪珠形状的参数
  963. const tdCenterX = element.width / 2
  964. const tdCenterY = element.height / 2
  965. const tdRadiusX = element.width / 2
  966. const tdRadiusY = element.height / 2
  967. // 使用相对比例计算控制点
  968. teardrop.setAttribute(
  969. "d",
  970. `M${tdCenterX * 2} ${tdCenterY} ` +
  971. `A ${tdRadiusX} ${tdRadiusY} 0 1 1 ${tdCenterX} 0 ` +
  972. `Q${tdCenterX * 1.7},0 ${tdCenterX * 2.1},${-tdCenterY * 0.1} ` +
  973. `Q${tdCenterX * 2},${tdCenterY * 0.29} ${
  974. tdCenterX * 2
  975. },${tdCenterY}`
  976. )
  977. // 设置填充色
  978. setBackground(element, teardrop)
  979. // 设置边框样式
  980. if (element.borderWidth > 0) {
  981. teardrop.setAttribute("stroke", element.borderColor || "#000")
  982. teardrop.setAttribute("stroke-width", element.borderWidth || 1)
  983. teardrop.setAttribute("stroke-linejoin", "round")
  984. // 处理虚线边框
  985. if (
  986. element.borderType === "dotted" ||
  987. element.borderType === "dashed"
  988. ) {
  989. // ... 原有的虚线边框处理代码 ...
  990. }
  991. }
  992. svg.appendChild(teardrop)
  993. break
  994. case "decagon":
  995. const decagon = document.createElementNS(
  996. "http://www.w3.org/2000/svg",
  997. "polygon"
  998. )
  999. // 计算十边形的顶点
  1000. let decagonPoints = ""
  1001. for (let i = 0; i < 10; i++) {
  1002. const angle = (i * 2 * Math.PI) / 10 - Math.PI / 2 // 从顶部开始
  1003. const x = element.width / 2 + (element.width / 2) * Math.cos(angle)
  1004. const y =
  1005. element.height / 2 + (element.height / 2) * Math.sin(angle)
  1006. decagonPoints += `${x},${y} `
  1007. }
  1008. decagon.setAttribute("points", decagonPoints.trim())
  1009. // 设置填充色
  1010. setBackground(element, decagon)
  1011. // 设置边框
  1012. if (element.borderWidth > 0) {
  1013. decagon.setAttribute("stroke", element.borderColor || "#000")
  1014. decagon.setAttribute("stroke-width", element.borderWidth || 1)
  1015. // 处理虚线边框
  1016. if (
  1017. element.borderType === "dotted" ||
  1018. element.borderType === "dashed"
  1019. ) {
  1020. if (element.borderStrokeDasharray) {
  1021. decagon.setAttribute(
  1022. "stroke-dasharray",
  1023. element.borderStrokeDasharray
  1024. )
  1025. } else if (element.borderType === "dotted") {
  1026. decagon.setAttribute("stroke-dasharray", "1, 3")
  1027. } else if (element.borderType === "dashed") {
  1028. decagon.setAttribute("stroke-dasharray", "5, 5")
  1029. }
  1030. }
  1031. }
  1032. svg.appendChild(decagon)
  1033. break
  1034. case "pentagon":
  1035. const pentagon = document.createElementNS(
  1036. "http://www.w3.org/2000/svg",
  1037. "polygon"
  1038. )
  1039. pentagon.setAttribute(
  1040. "points",
  1041. `${element.width / 2},0 ${element.width},${
  1042. element.height * 0.38
  1043. } ` +
  1044. `${element.width * 0.82},${element.height} ${
  1045. element.width * 0.18
  1046. },${element.height} ` +
  1047. `0,${element.height * 0.38}`
  1048. )
  1049. // 设置填充色
  1050. setBackground(element, pentagon)
  1051. // 设置边框
  1052. if (element.borderWidth > 0) {
  1053. pentagon.setAttribute("stroke", element.borderColor || "#000")
  1054. pentagon.setAttribute("stroke-width", element.borderWidth || 1)
  1055. // 处理虚线边框
  1056. if (
  1057. element.borderType === "dotted" ||
  1058. element.borderType === "dashed"
  1059. ) {
  1060. if (element.borderStrokeDasharray) {
  1061. pentagon.setAttribute(
  1062. "stroke-dasharray",
  1063. element.borderStrokeDasharray
  1064. )
  1065. } else if (element.borderType === "dotted") {
  1066. pentagon.setAttribute("stroke-dasharray", "1, 3")
  1067. } else if (element.borderType === "dashed") {
  1068. pentagon.setAttribute("stroke-dasharray", "5, 5")
  1069. }
  1070. }
  1071. }
  1072. svg.appendChild(pentagon)
  1073. break
  1074. case "pie":
  1075. const pie = document.createElementNS(
  1076. "http://www.w3.org/2000/svg",
  1077. "path"
  1078. )
  1079. // 使用提供的路径数据,但保留元素的宽高比例
  1080. const centerX = element.width / 2
  1081. const centerY = element.height / 2
  1082. const radius2 = Math.min(element.width, element.height) / 2
  1083. // 绘制饼图,使用类似提供的路径数据
  1084. pie.setAttribute(
  1085. "d",
  1086. `M${centerX},${centerY} ` +
  1087. `L${centerX * 1.85},${centerY * 1.52} ` +
  1088. `A${radius2},${radius2} 0 1,1 ${centerX * 1.56},${
  1089. centerY * 0.17
  1090. } ` +
  1091. `Z`
  1092. )
  1093. // 设置填充色
  1094. setBackground(element, pie)
  1095. // 设置边框
  1096. if (element.borderWidth > 0) {
  1097. pie.setAttribute("stroke", element.borderColor || "#000")
  1098. pie.setAttribute("stroke-width", element.borderWidth || 1)
  1099. // 处理虚线边框
  1100. if (
  1101. element.borderType === "dotted" ||
  1102. element.borderType === "dashed"
  1103. ) {
  1104. if (element.borderStrokeDasharray) {
  1105. pie.setAttribute(
  1106. "stroke-dasharray",
  1107. element.borderStrokeDasharray
  1108. )
  1109. } else if (element.borderType === "dotted") {
  1110. pie.setAttribute("stroke-dasharray", "2, 2")
  1111. pie.setAttribute("stroke-linecap", "round")
  1112. } else if (element.borderType === "dashed") {
  1113. pie.setAttribute("stroke-dasharray", "6, 3")
  1114. }
  1115. }
  1116. pie.setAttribute("vector-effect", "non-scaling-stroke")
  1117. pie.setAttribute("shape-rendering", "geometricPrecision")
  1118. }
  1119. svg.appendChild(pie)
  1120. break
  1121. case "chord":
  1122. const chord = document.createElementNS(
  1123. "http://www.w3.org/2000/svg",
  1124. "path"
  1125. )
  1126. // 计算弦形的参数
  1127. const chordRadiusX = element.width * 0.4
  1128. const chordRadiusY = element.height * 0.4
  1129. // 绘制弦形 - 使用更大的圆弧和不同的起始/结束点
  1130. chord.setAttribute(
  1131. "d",
  1132. `M${element.width * 0.4},${element.height * 0.9} ` +
  1133. `A ${chordRadiusX} ${chordRadiusY} 0 1 1 ${element.width * 0.8},${
  1134. element.height * 0.5
  1135. } ` +
  1136. `Z`
  1137. )
  1138. // 设置填充色
  1139. setBackground(element, chord)
  1140. // 设置边框
  1141. if (element.borderWidth > 0) {
  1142. chord.setAttribute("stroke", element.borderColor || "#000")
  1143. chord.setAttribute("stroke-width", element.borderWidth || 1)
  1144. // 处理虚线边框
  1145. if (
  1146. element.borderType === "dotted" ||
  1147. element.borderType === "dashed"
  1148. ) {
  1149. if (element.borderStrokeDasharray) {
  1150. chord.setAttribute(
  1151. "stroke-dasharray",
  1152. element.borderStrokeDasharray
  1153. )
  1154. } else if (element.borderType === "dotted") {
  1155. chord.setAttribute("stroke-dasharray", "2, 2")
  1156. chord.setAttribute("stroke-linecap", "round")
  1157. } else if (element.borderType === "dashed") {
  1158. chord.setAttribute("stroke-dasharray", "6, 3")
  1159. }
  1160. }
  1161. chord.setAttribute("vector-effect", "non-scaling-stroke")
  1162. chord.setAttribute("shape-rendering", "geometricPrecision")
  1163. }
  1164. svg.appendChild(chord)
  1165. break
  1166. case "heptagon":
  1167. const heptagon = document.createElementNS(
  1168. "http://www.w3.org/2000/svg",
  1169. "polygon"
  1170. )
  1171. // 计算七边形的顶点
  1172. let heptagonPoints = ""
  1173. for (let i = 0; i < 7; i++) {
  1174. const angle = (i * 2 * Math.PI) / 7 - Math.PI / 2 // 从顶部开始
  1175. const x = element.width / 2 + (element.width / 2) * Math.cos(angle)
  1176. const y =
  1177. element.height / 2 + (element.height / 2) * Math.sin(angle)
  1178. heptagonPoints += `${x},${y} `
  1179. }
  1180. heptagon.setAttribute("points", heptagonPoints.trim())
  1181. // 设置填充色
  1182. setBackground(element, heptagon)
  1183. // 设置边框
  1184. if (element.borderWidth > 0) {
  1185. heptagon.setAttribute("stroke", element.borderColor || "#000")
  1186. heptagon.setAttribute("stroke-width", element.borderWidth || 1)
  1187. // 处理虚线边框
  1188. if (
  1189. element.borderType === "dotted" ||
  1190. element.borderType === "dashed"
  1191. ) {
  1192. if (element.borderStrokeDasharray) {
  1193. heptagon.setAttribute(
  1194. "stroke-dasharray",
  1195. element.borderStrokeDasharray
  1196. )
  1197. } else if (element.borderType === "dotted") {
  1198. heptagon.setAttribute("stroke-dasharray", "1, 3")
  1199. } else if (element.borderType === "dashed") {
  1200. heptagon.setAttribute("stroke-dasharray", "5, 5")
  1201. }
  1202. }
  1203. }
  1204. svg.appendChild(heptagon)
  1205. break
  1206. case "hexagon":
  1207. const hexagon = document.createElementNS(
  1208. "http://www.w3.org/2000/svg",
  1209. "polygon"
  1210. )
  1211. hexagon.setAttribute(
  1212. "points",
  1213. `${element.width * 0.25},0 ${element.width * 0.75},0 ${
  1214. element.width
  1215. },${element.height * 0.5} ` +
  1216. `${element.width * 0.75},${element.height} ${
  1217. element.width * 0.25
  1218. },${element.height} 0,${element.height * 0.5}`
  1219. )
  1220. // 设置填充色
  1221. setBackground(element, hexagon)
  1222. // 设置边框
  1223. if (element.borderWidth > 0) {
  1224. hexagon.setAttribute("stroke", element.borderColor || "#000")
  1225. hexagon.setAttribute("stroke-width", element.borderWidth || 1)
  1226. // 处理虚线边框
  1227. if (
  1228. element.borderType === "dotted" ||
  1229. element.borderType === "dashed"
  1230. ) {
  1231. if (element.borderStrokeDasharray) {
  1232. hexagon.setAttribute(
  1233. "stroke-dasharray",
  1234. element.borderStrokeDasharray
  1235. )
  1236. } else if (element.borderType === "dotted") {
  1237. hexagon.setAttribute("stroke-dasharray", "1, 3")
  1238. } else if (element.borderType === "dashed") {
  1239. hexagon.setAttribute("stroke-dasharray", "5, 5")
  1240. }
  1241. }
  1242. }
  1243. svg.appendChild(hexagon)
  1244. break
  1245. case "octagon":
  1246. const octagon = document.createElementNS(
  1247. "http://www.w3.org/2000/svg",
  1248. "polygon"
  1249. )
  1250. octagon.setAttribute(
  1251. "points",
  1252. `${element.width * 0.3},0 ${element.width * 0.7},0 ${
  1253. element.width
  1254. },${element.height * 0.3} ` +
  1255. `${element.width},${element.height * 0.7} ${
  1256. element.width * 0.7
  1257. },${element.height} ` +
  1258. `${element.width * 0.3},${element.height} 0,${
  1259. element.height * 0.7
  1260. } 0,${element.height * 0.3}`
  1261. )
  1262. // 设置填充色
  1263. setBackground(element, octagon)
  1264. // 设置边框
  1265. if (element.borderWidth > 0) {
  1266. octagon.setAttribute("stroke", element.borderColor || "#000")
  1267. octagon.setAttribute("stroke-width", element.borderWidth || 1)
  1268. // 处理虚线边框
  1269. if (
  1270. element.borderType === "dotted" ||
  1271. element.borderType === "dashed"
  1272. ) {
  1273. if (element.borderStrokeDasharray) {
  1274. octagon.setAttribute(
  1275. "stroke-dasharray",
  1276. element.borderStrokeDasharray
  1277. )
  1278. } else if (element.borderType === "dotted") {
  1279. octagon.setAttribute("stroke-dasharray", "1, 3")
  1280. } else if (element.borderType === "dashed") {
  1281. octagon.setAttribute("stroke-dasharray", "5, 5")
  1282. }
  1283. }
  1284. }
  1285. svg.appendChild(octagon)
  1286. break
  1287. case "trapezoid":
  1288. const trapezoid = document.createElementNS(
  1289. "http://www.w3.org/2000/svg",
  1290. "polygon"
  1291. )
  1292. trapezoid.setAttribute(
  1293. "points",
  1294. `${element.width * 0.2},0 ${element.width * 0.8},0 ${
  1295. element.width
  1296. },${element.height} 0,${element.height}`
  1297. )
  1298. // 设置填充色
  1299. setBackground(element, trapezoid)
  1300. // 设置边框
  1301. if (element.borderWidth > 0) {
  1302. trapezoid.setAttribute("stroke", element.borderColor || "#000")
  1303. trapezoid.setAttribute("stroke-width", element.borderWidth || 1)
  1304. // 处理虚线边框
  1305. if (
  1306. element.borderType === "dotted" ||
  1307. element.borderType === "dashed"
  1308. ) {
  1309. if (element.borderStrokeDasharray) {
  1310. trapezoid.setAttribute(
  1311. "stroke-dasharray",
  1312. element.borderStrokeDasharray
  1313. )
  1314. } else if (element.borderType === "dotted") {
  1315. trapezoid.setAttribute("stroke-dasharray", "1, 3")
  1316. } else if (element.borderType === "dashed") {
  1317. trapezoid.setAttribute("stroke-dasharray", "5, 5")
  1318. }
  1319. }
  1320. }
  1321. svg.appendChild(trapezoid)
  1322. break
  1323. case "diamond":
  1324. const diamond = document.createElementNS(
  1325. "http://www.w3.org/2000/svg",
  1326. "polygon"
  1327. )
  1328. diamond.setAttribute(
  1329. "points",
  1330. `${element.width / 2},0 ${element.width},${element.height / 2} ${
  1331. element.width / 2
  1332. },${element.height} 0,${element.height / 2}`
  1333. )
  1334. // 设置填充色
  1335. setBackground(element, diamond)
  1336. // 设置边框
  1337. if (element.borderWidth > 0) {
  1338. diamond.setAttribute("stroke", element.borderColor || "#000")
  1339. diamond.setAttribute("stroke-width", element.borderWidth || 1)
  1340. // 处理虚线边框
  1341. if (
  1342. element.borderType === "dotted" ||
  1343. element.borderType === "dashed"
  1344. ) {
  1345. if (element.borderStrokeDasharray) {
  1346. diamond.setAttribute(
  1347. "stroke-dasharray",
  1348. element.borderStrokeDasharray
  1349. )
  1350. } else if (element.borderType === "dotted") {
  1351. diamond.setAttribute("stroke-dasharray", "1, 3")
  1352. } else if (element.borderType === "dashed") {
  1353. diamond.setAttribute("stroke-dasharray", "5, 5")
  1354. }
  1355. }
  1356. }
  1357. svg.appendChild(diamond)
  1358. break
  1359. case "dodecagon":
  1360. const dodecagon = document.createElementNS(
  1361. "http://www.w3.org/2000/svg",
  1362. "polygon"
  1363. )
  1364. // 计算十二边形的顶点
  1365. let dodecagonPoints = ""
  1366. for (let i = 0; i < 12; i++) {
  1367. const angle = (i * 2 * Math.PI) / 12 - Math.PI / 2 // 从顶部开始
  1368. const x = element.width / 2 + (element.width / 2) * Math.cos(angle)
  1369. const y =
  1370. element.height / 2 + (element.height / 2) * Math.sin(angle)
  1371. dodecagonPoints += `${x},${y} `
  1372. }
  1373. dodecagon.setAttribute("points", dodecagonPoints.trim())
  1374. // 设置填充色
  1375. setBackground(element, dodecagon)
  1376. // 设置边框
  1377. if (element.borderWidth > 0) {
  1378. dodecagon.setAttribute("stroke", element.borderColor || "#000")
  1379. dodecagon.setAttribute("stroke-width", element.borderWidth || 1)
  1380. // 处理虚线边框
  1381. if (
  1382. element.borderType === "dotted" ||
  1383. element.borderType === "dashed"
  1384. ) {
  1385. if (element.borderStrokeDasharray) {
  1386. dodecagon.setAttribute(
  1387. "stroke-dasharray",
  1388. element.borderStrokeDasharray
  1389. )
  1390. } else if (element.borderType === "dotted") {
  1391. dodecagon.setAttribute("stroke-dasharray", "1, 3")
  1392. } else if (element.borderType === "dashed") {
  1393. dodecagon.setAttribute("stroke-dasharray", "5, 5")
  1394. }
  1395. }
  1396. }
  1397. svg.appendChild(dodecagon)
  1398. break
  1399. case "halfFrame":
  1400. // 创建外框和内框
  1401. const outerRect2 = document.createElementNS(
  1402. "http://www.w3.org/2000/svg",
  1403. "path"
  1404. )
  1405. const innerRect2 = document.createElementNS(
  1406. "http://www.w3.org/2000/svg",
  1407. "path"
  1408. )
  1409. // 计算内框的边距
  1410. const frameWidth2 = element.width / 9
  1411. // 绘制外框的左边和上边
  1412. outerRect2.setAttribute(
  1413. "d",
  1414. `M0,${element.height} L0,0 L${element.width},0`
  1415. )
  1416. // 绘制内框的左边和上边,注意起点位置调整
  1417. innerRect2.setAttribute(
  1418. "d",
  1419. `M${frameWidth2},${element.height - frameWidth2} ` +
  1420. `L${frameWidth2},${frameWidth2} ` +
  1421. `L${element.width - frameWidth2},${frameWidth2}`
  1422. )
  1423. // 设置填充色
  1424. if (element.fill && element.fill.type === "color") {
  1425. // 创建一个填充用的路径
  1426. const fillPath = document.createElementNS(
  1427. "http://www.w3.org/2000/svg",
  1428. "path"
  1429. )
  1430. fillPath.setAttribute(
  1431. "d",
  1432. `M${frameWidth2},${frameWidth2} ` +
  1433. `L${element.width - frameWidth2},${frameWidth2} ` +
  1434. `L${element.width},0 ` +
  1435. `L0,0 ` +
  1436. `L0,${element.height} ` +
  1437. `L${frameWidth2},${element.height - frameWidth2} Z`
  1438. )
  1439. fillPath.setAttribute("fill", element.fill.value || "transparent")
  1440. svg.appendChild(fillPath)
  1441. outerRect2.setAttribute("fill", "none")
  1442. innerRect2.setAttribute("fill", "none")
  1443. } else {
  1444. outerRect2.setAttribute("fill", "none")
  1445. innerRect2.setAttribute("fill", "none")
  1446. }
  1447. // 设置边框
  1448. if (element.borderWidth > 0) {
  1449. const borderColor = element.borderColor || "#000"
  1450. const borderWidth = element.borderWidth || 1
  1451. outerRect2.setAttribute("stroke", borderColor)
  1452. outerRect2.setAttribute("stroke-width", borderWidth)
  1453. innerRect2.setAttribute("stroke", borderColor)
  1454. innerRect2.setAttribute("stroke-width", borderWidth)
  1455. // 处理虚线边框
  1456. if (
  1457. element.borderType === "dotted" ||
  1458. element.borderType === "dashed"
  1459. ) {
  1460. if (element.borderStrokeDasharray) {
  1461. const dashArray = element.borderStrokeDasharray
  1462. outerRect2.setAttribute("stroke-dasharray", dashArray)
  1463. innerRect2.setAttribute("stroke-dasharray", dashArray)
  1464. } else if (element.borderType === "dotted") {
  1465. outerRect2.setAttribute("stroke-dasharray", "1, 3")
  1466. innerRect2.setAttribute("stroke-dasharray", "1, 3")
  1467. } else if (element.borderType === "dashed") {
  1468. outerRect2.setAttribute("stroke-dasharray", "5, 5")
  1469. innerRect2.setAttribute("stroke-dasharray", "5, 5")
  1470. }
  1471. }
  1472. }
  1473. svg.appendChild(outerRect2)
  1474. svg.appendChild(innerRect2)
  1475. break
  1476. case "corner":
  1477. const corner = document.createElementNS(
  1478. "http://www.w3.org/2000/svg",
  1479. "path"
  1480. )
  1481. corner.setAttribute(
  1482. "d",
  1483. `M0,0 ` +
  1484. `L0,${element.height} ` +
  1485. `L${element.width},${element.height} ` +
  1486. `L${element.width},${element.height * 0.6} ` +
  1487. `L${element.width * 0.4},${element.height * 0.6} ` +
  1488. `L${element.width * 0.4},0 Z`
  1489. )
  1490. // 设置填充色
  1491. setBackground(element, corner)
  1492. // 设置边框
  1493. if (element.borderWidth > 0) {
  1494. corner.setAttribute("stroke", element.borderColor || "#000")
  1495. corner.setAttribute("stroke-width", element.borderWidth || 1)
  1496. // 处理虚线边框
  1497. if (
  1498. element.borderType === "dotted" ||
  1499. element.borderType === "dashed"
  1500. ) {
  1501. if (element.borderStrokeDasharray) {
  1502. corner.setAttribute(
  1503. "stroke-dasharray",
  1504. element.borderStrokeDasharray
  1505. )
  1506. } else if (element.borderType === "dotted") {
  1507. corner.setAttribute("stroke-dasharray", "1, 3")
  1508. } else if (element.borderType === "dashed") {
  1509. corner.setAttribute("stroke-dasharray", "5, 5")
  1510. }
  1511. }
  1512. }
  1513. svg.appendChild(corner)
  1514. break
  1515. case "diagStripe":
  1516. const diagStripe = document.createElementNS(
  1517. "http://www.w3.org/2000/svg",
  1518. "path"
  1519. )
  1520. // 绘制斜纹路径
  1521. diagStripe.setAttribute(
  1522. "d",
  1523. `M${element.width * 0.4},0 ` +
  1524. `L${element.width},0 ` +
  1525. `L0,${element.height} ` +
  1526. `L0,${element.height * 0.4} Z`
  1527. )
  1528. // 设置填充色
  1529. setBackground(element, diagStripe)
  1530. // 设置边框
  1531. if (element.borderWidth > 0) {
  1532. diagStripe.setAttribute("stroke", element.borderColor || "#000")
  1533. diagStripe.setAttribute("stroke-width", element.borderWidth || 1)
  1534. diagStripe.setAttribute("stroke-linejoin", "round")
  1535. // 处理虚线边框
  1536. if (
  1537. element.borderType === "dotted" ||
  1538. element.borderType === "dashed"
  1539. ) {
  1540. if (element.borderStrokeDasharray) {
  1541. diagStripe.setAttribute(
  1542. "stroke-dasharray",
  1543. element.borderStrokeDasharray
  1544. )
  1545. } else if (element.borderType === "dotted") {
  1546. diagStripe.setAttribute("stroke-dasharray", "1, 3")
  1547. } else if (element.borderType === "dashed") {
  1548. diagStripe.setAttribute("stroke-dasharray", "5, 5")
  1549. }
  1550. }
  1551. }
  1552. svg.appendChild(diagStripe)
  1553. break
  1554. case "plus":
  1555. const plus = document.createElementNS(
  1556. "http://www.w3.org/2000/svg",
  1557. "polygon"
  1558. )
  1559. plus.setAttribute(
  1560. "points",
  1561. `${element.width * 0.4},0 ` +
  1562. `${element.width * 0.6},0 ` +
  1563. `${element.width * 0.6},${element.height * 0.4} ` +
  1564. `${element.width},${element.height * 0.4} ` +
  1565. `${element.width},${element.height * 0.6} ` +
  1566. `${element.width * 0.6},${element.height * 0.6} ` +
  1567. `${element.width * 0.6},${element.height} ` +
  1568. `${element.width * 0.4},${element.height} ` +
  1569. `${element.width * 0.4},${element.height * 0.6} ` +
  1570. `0,${element.height * 0.6} ` +
  1571. `0,${element.height * 0.4} ` +
  1572. `${element.width * 0.4},${element.height * 0.4}`
  1573. )
  1574. // 设置填充色
  1575. setBackground(element, plus)
  1576. // 设置边框
  1577. if (element.borderWidth > 0) {
  1578. plus.setAttribute("stroke", element.borderColor || "#000")
  1579. plus.setAttribute("stroke-width", element.borderWidth || 1)
  1580. // 处理虚线边框
  1581. if (
  1582. element.borderType === "dotted" ||
  1583. element.borderType === "dashed"
  1584. ) {
  1585. if (element.borderStrokeDasharray) {
  1586. plus.setAttribute(
  1587. "stroke-dasharray",
  1588. element.borderStrokeDasharray
  1589. )
  1590. } else if (element.borderType === "dotted") {
  1591. plus.setAttribute("stroke-dasharray", "1, 3")
  1592. } else if (element.borderType === "dashed") {
  1593. plus.setAttribute("stroke-dasharray", "5, 5")
  1594. }
  1595. }
  1596. }
  1597. svg.appendChild(plus)
  1598. break
  1599. case "can":
  1600. const can = document.createElementNS(
  1601. "http://www.w3.org/2000/svg",
  1602. "g"
  1603. )
  1604. // 创建圆柱体的主体部分
  1605. const cylinderBody = document.createElementNS(
  1606. "http://www.w3.org/2000/svg",
  1607. "path"
  1608. )
  1609. cylinderBody.setAttribute(
  1610. "d",
  1611. `M0,${element.height * 0.15} ` +
  1612. `A${element.width / 2},${element.height * 0.15} 0 0 1 ${
  1613. element.width
  1614. },${element.height * 0.15} ` +
  1615. `V${element.height * 0.85} ` +
  1616. `A${element.width / 2},${element.height * 0.15} 0 0 1 0,${
  1617. element.height * 0.85
  1618. } Z`
  1619. )
  1620. // 创建顶部椭圆
  1621. const topEllipse = document.createElementNS(
  1622. "http://www.w3.org/2000/svg",
  1623. "ellipse"
  1624. )
  1625. topEllipse.setAttribute("cx", element.width / 2)
  1626. topEllipse.setAttribute("cy", element.height * 0.15)
  1627. topEllipse.setAttribute("rx", element.width / 2)
  1628. topEllipse.setAttribute("ry", element.height * 0.15)
  1629. // 设置填充色
  1630. setBackground(element, cylinderBody)
  1631. setBackground(element, topEllipse)
  1632. // 设置边框
  1633. if (element.borderWidth > 0) {
  1634. const borderColor = element.borderColor || "#000"
  1635. const borderWidth = element.borderWidth || 1
  1636. cylinderBody.setAttribute("stroke", borderColor)
  1637. cylinderBody.setAttribute("stroke-width", borderWidth)
  1638. topEllipse.setAttribute("stroke", borderColor)
  1639. topEllipse.setAttribute("stroke-width", borderWidth)
  1640. // 处理虚线边框
  1641. if (
  1642. element.borderType === "dotted" ||
  1643. element.borderType === "dashed"
  1644. ) {
  1645. if (element.borderStrokeDasharray) {
  1646. const dashArray = element.borderStrokeDasharray
  1647. cylinderBody.setAttribute("stroke-dasharray", dashArray)
  1648. topEllipse.setAttribute("stroke-dasharray", dashArray)
  1649. } else if (element.borderType === "dotted") {
  1650. cylinderBody.setAttribute("stroke-dasharray", "1, 3")
  1651. topEllipse.setAttribute("stroke-dasharray", "1, 3")
  1652. } else if (element.borderType === "dashed") {
  1653. cylinderBody.setAttribute("stroke-dasharray", "5, 5")
  1654. topEllipse.setAttribute("stroke-dasharray", "5, 5")
  1655. }
  1656. }
  1657. }
  1658. can.appendChild(cylinderBody)
  1659. can.appendChild(topEllipse)
  1660. svg.appendChild(can)
  1661. break
  1662. case "cube":
  1663. const cube = document.createElementNS(
  1664. "http://www.w3.org/2000/svg",
  1665. "g"
  1666. )
  1667. // 计算关键点坐标
  1668. const offset = element.width * 0.2
  1669. const frontX = offset
  1670. const frontY = offset
  1671. const frontW = element.width - offset
  1672. const frontH = element.height
  1673. // 设置立方体的三个面的路径
  1674. const frontFace = document.createElementNS(
  1675. "http://www.w3.org/2000/svg",
  1676. "path"
  1677. )
  1678. frontFace.setAttribute(
  1679. "d",
  1680. `M${frontX},${frontY} ` +
  1681. `L${frontW},${frontY} ` +
  1682. `L${frontW},${frontH} ` +
  1683. `L${frontX},${frontH} Z`
  1684. )
  1685. const rightFace = document.createElementNS(
  1686. "http://www.w3.org/2000/svg",
  1687. "path"
  1688. )
  1689. rightFace.setAttribute(
  1690. "d",
  1691. `M${frontW},${frontY} ` +
  1692. `L${element.width},0 ` +
  1693. `L${element.width},${element.height - offset} ` +
  1694. `L${frontW},${frontH} Z`
  1695. )
  1696. const topFace = document.createElementNS(
  1697. "http://www.w3.org/2000/svg",
  1698. "path"
  1699. )
  1700. topFace.setAttribute(
  1701. "d",
  1702. `M${frontX},${frontY} ` +
  1703. `L${frontW - offset - frontX},0 ` + // 修改这里:改为从(0,0)开始
  1704. `L${element.width - offset},0 ` + // 修改这里:使用 offset 来计算右上角的位置
  1705. `L${element.width},0 ` +
  1706. `L${frontW},${frontY} Z`
  1707. )
  1708. // 设置填充色
  1709. if (element.fill && element.fill.type === "color") {
  1710. const fillColor = element.fill.value || "transparent"
  1711. frontFace.setAttribute("fill", fillColor)
  1712. rightFace.setAttribute(
  1713. "fill",
  1714. this.adjustBrightness(fillColor, 0.8)
  1715. )
  1716. topFace.setAttribute("fill", this.adjustBrightness(fillColor, 1.2))
  1717. } else {
  1718. frontFace.setAttribute("fill", "transparent")
  1719. rightFace.setAttribute("fill", "transparent")
  1720. topFace.setAttribute("fill", "transparent")
  1721. }
  1722. // 设置边框
  1723. if (element.borderWidth > 0) {
  1724. const borderColor = element.borderColor || "#000"
  1725. const borderWidth = element.borderWidth || 1
  1726. frontFace.setAttribute("stroke", borderColor)
  1727. frontFace.setAttribute("stroke-width", borderWidth)
  1728. rightFace.setAttribute("stroke", borderColor)
  1729. rightFace.setAttribute("stroke-width", borderWidth)
  1730. topFace.setAttribute("stroke", borderColor)
  1731. topFace.setAttribute("stroke-width", borderWidth)
  1732. if (
  1733. element.borderType === "dotted" ||
  1734. element.borderType === "dashed"
  1735. ) {
  1736. const dashArray =
  1737. element.borderStrokeDasharray ||
  1738. (element.borderType === "dotted" ? "1, 3" : "5, 5")
  1739. frontFace.setAttribute("stroke-dasharray", dashArray)
  1740. rightFace.setAttribute("stroke-dasharray", dashArray)
  1741. topFace.setAttribute("stroke-dasharray", dashArray)
  1742. }
  1743. }
  1744. // 按正确的顺序添加面(从后到前)
  1745. cube.appendChild(rightFace)
  1746. cube.appendChild(topFace)
  1747. cube.appendChild(frontFace)
  1748. svg.appendChild(cube)
  1749. break
  1750. case "bevel":
  1751. const bevel = document.createElementNS(
  1752. "http://www.w3.org/2000/svg",
  1753. "g"
  1754. )
  1755. // 计算关键点坐标
  1756. const bevelOffset = element.width * 0.2
  1757. const smallRectX = bevelOffset
  1758. const smallRectY = bevelOffset
  1759. const smallRectW = element.width - 2 * bevelOffset
  1760. const smallRectH = element.height - 2 * bevelOffset
  1761. // 绘制顶部小矩形
  1762. const topRect = document.createElementNS(
  1763. "http://www.w3.org/2000/svg",
  1764. "rect"
  1765. )
  1766. topRect.setAttribute("x", smallRectX)
  1767. topRect.setAttribute("y", smallRectY)
  1768. topRect.setAttribute("width", smallRectW)
  1769. topRect.setAttribute("height", smallRectH)
  1770. // 绘制四个梯形
  1771. const topTrapezoid = document.createElementNS(
  1772. "http://www.w3.org/2000/svg",
  1773. "path"
  1774. )
  1775. topTrapezoid.setAttribute(
  1776. "d",
  1777. `M0,0 L${element.width},0 L${
  1778. element.width - bevelOffset
  1779. },${bevelOffset} L${bevelOffset},${bevelOffset} Z`
  1780. )
  1781. const bottomTrapezoid = document.createElementNS(
  1782. "http://www.w3.org/2000/svg",
  1783. "path"
  1784. )
  1785. bottomTrapezoid.setAttribute(
  1786. "d",
  1787. `M${bevelOffset},${element.height - bevelOffset} L${
  1788. element.width - bevelOffset
  1789. },${element.height - bevelOffset} L${element.width},${
  1790. element.height
  1791. } L0,${element.height} Z`
  1792. )
  1793. const leftTrapezoid = document.createElementNS(
  1794. "http://www.w3.org/2000/svg",
  1795. "path"
  1796. )
  1797. leftTrapezoid.setAttribute(
  1798. "d",
  1799. `M0,0 L${bevelOffset},${bevelOffset} L${bevelOffset},${
  1800. element.height - bevelOffset
  1801. } L0,${element.height} Z`
  1802. )
  1803. const rightTrapezoid = document.createElementNS(
  1804. "http://www.w3.org/2000/svg",
  1805. "path"
  1806. )
  1807. rightTrapezoid.setAttribute(
  1808. "d",
  1809. `M${element.width},0 L${element.width},${element.height} L${
  1810. element.width - bevelOffset
  1811. },${element.height - bevelOffset} L${
  1812. element.width - bevelOffset
  1813. },${bevelOffset} Z`
  1814. )
  1815. // 设置填充色
  1816. if (element.fill && element.fill.type === "color") {
  1817. const fillColor = element.fill.value || "transparent"
  1818. topRect.setAttribute("fill", fillColor)
  1819. topTrapezoid.setAttribute(
  1820. "fill",
  1821. this.adjustBrightness(fillColor, 1.2)
  1822. )
  1823. bottomTrapezoid.setAttribute(
  1824. "fill",
  1825. this.adjustBrightness(fillColor, 0.8)
  1826. )
  1827. leftTrapezoid.setAttribute(
  1828. "fill",
  1829. this.adjustBrightness(fillColor, 0.9)
  1830. )
  1831. rightTrapezoid.setAttribute(
  1832. "fill",
  1833. this.adjustBrightness(fillColor, 0.7)
  1834. )
  1835. } else {
  1836. topRect.setAttribute("fill", "transparent")
  1837. topTrapezoid.setAttribute("fill", "transparent")
  1838. bottomTrapezoid.setAttribute("fill", "transparent")
  1839. leftTrapezoid.setAttribute("fill", "transparent")
  1840. rightTrapezoid.setAttribute("fill", "transparent")
  1841. }
  1842. // 设置边框
  1843. if (element.borderWidth > 0) {
  1844. const borderColor = element.borderColor || "#000"
  1845. const borderWidth = element.borderWidth || 1
  1846. const parts = [
  1847. topRect,
  1848. topTrapezoid,
  1849. bottomTrapezoid,
  1850. leftTrapezoid,
  1851. rightTrapezoid,
  1852. ]
  1853. parts.forEach((part) => {
  1854. part.setAttribute("stroke", borderColor)
  1855. part.setAttribute("stroke-width", borderWidth)
  1856. if (
  1857. element.borderType === "dotted" ||
  1858. element.borderType === "dashed"
  1859. ) {
  1860. const dashArray =
  1861. element.borderStrokeDasharray ||
  1862. (element.borderType === "dotted" ? "1, 3" : "5, 5")
  1863. part.setAttribute("stroke-dasharray", dashArray)
  1864. }
  1865. })
  1866. }
  1867. // 按正确的顺序添加面(从后到前)
  1868. bevel.appendChild(bottomTrapezoid)
  1869. bevel.appendChild(leftTrapezoid)
  1870. bevel.appendChild(rightTrapezoid)
  1871. bevel.appendChild(topTrapezoid)
  1872. bevel.appendChild(topRect)
  1873. svg.appendChild(bevel)
  1874. break
  1875. case "donut":
  1876. const donut = document.createElementNS(
  1877. "http://www.w3.org/2000/svg",
  1878. "g"
  1879. )
  1880. // 外圆
  1881. const outerCircle = document.createElementNS(
  1882. "http://www.w3.org/2000/svg",
  1883. "circle"
  1884. )
  1885. outerCircle.setAttribute("cx", element.width / 2)
  1886. outerCircle.setAttribute("cy", element.height / 2)
  1887. outerCircle.setAttribute(
  1888. "r",
  1889. Math.min(element.width, element.height) / 2
  1890. )
  1891. // 内圆
  1892. const innerCircle = document.createElementNS(
  1893. "http://www.w3.org/2000/svg",
  1894. "circle"
  1895. )
  1896. const fmla = element?.formulas[0].split(" ")[1]
  1897. innerCircle.setAttribute("cx", element.width / 2)
  1898. innerCircle.setAttribute("cy", element.height / 2)
  1899. innerCircle.setAttribute(
  1900. "r",
  1901. (Math.min(element.width, element.height) / 2) *
  1902. (1 - Math.sqrt(fmla / 100000) / 2)
  1903. )
  1904. // 设置填充色
  1905. setBackground(element, outerCircle)
  1906. innerCircle.setAttribute("fill", "white")
  1907. // 设置边框
  1908. if (element.borderWidth > 0) {
  1909. const borderColor = element.borderColor || "#000"
  1910. const borderWidth = element.borderWidth || 1
  1911. outerCircle.setAttribute("stroke", borderColor)
  1912. outerCircle.setAttribute("stroke-width", borderWidth)
  1913. innerCircle.setAttribute("stroke", borderColor)
  1914. innerCircle.setAttribute("stroke-width", borderWidth)
  1915. if (
  1916. element.borderType === "dotted" ||
  1917. element.borderType === "dashed"
  1918. ) {
  1919. const dashArray =
  1920. element.borderStrokeDasharray ||
  1921. (element.borderType === "dotted" ? "1, 3" : "5, 5")
  1922. outerCircle.setAttribute("stroke-dasharray", dashArray)
  1923. innerCircle.setAttribute("stroke-dasharray", dashArray)
  1924. }
  1925. }
  1926. donut.appendChild(outerCircle)
  1927. donut.appendChild(innerCircle)
  1928. svg.appendChild(donut)
  1929. break
  1930. case "noSmoking":
  1931. const noSmoking = document.createElementNS(
  1932. "http://www.w3.org/2000/svg",
  1933. "g"
  1934. )
  1935. // 创建路径
  1936. const path = document.createElementNS(
  1937. "http://www.w3.org/2000/svg",
  1938. "path"
  1939. )
  1940. path.setAttribute(
  1941. "d",
  1942. "M0,70 A77,70 0 1,1 0,71 Z M123.80284467265982,99.39738105155146 A57.5386,50.5386 0 0 0 45.160427644134444,27.90427466198293 Z M30.197155327340184,40.602618948448544 A57.5386,50.5386 0 0 0 108.83957235586556,112.09572533801708 Z"
  1943. )
  1944. path.setAttribute("fill", "rgba(255,217,102,1)")
  1945. path.setAttribute("stroke", "rgba(23,44,81,1)")
  1946. path.setAttribute("stroke-width", "1px")
  1947. path.setAttribute("stroke-dasharray", "")
  1948. path.setAttribute("stroke-linecap", "butt")
  1949. path.setAttribute("stroke-linejoin", "round")
  1950. noSmoking.appendChild(path)
  1951. svg.appendChild(noSmoking)
  1952. break
  1953. case "rightArrow":
  1954. const rightArrow = document.createElementNS(
  1955. "http://www.w3.org/2000/svg",
  1956. "polygon"
  1957. )
  1958. rightArrow.setAttribute(
  1959. "points",
  1960. `0,${element.height * 0.3} ${element.width * 0.7},${
  1961. element.height * 0.3
  1962. } ` +
  1963. `${element.width * 0.7},0 ${element.width},${
  1964. element.height * 0.5
  1965. } ` +
  1966. `${element.width * 0.7},${element.height} ${
  1967. element.width * 0.7
  1968. },${element.height * 0.7} ` +
  1969. `0,${element.height * 0.7}`
  1970. )
  1971. // 设置填充色
  1972. setBackground(element, rightArrow)
  1973. // 设置边框
  1974. if (element.borderWidth > 0) {
  1975. rightArrow.setAttribute("stroke", element.borderColor || "#000")
  1976. rightArrow.setAttribute("stroke-width", element.borderWidth || 1)
  1977. // 处理虚线边框
  1978. if (
  1979. element.borderType === "dotted" ||
  1980. element.borderType === "dashed"
  1981. ) {
  1982. if (element.borderStrokeDasharray) {
  1983. rightArrow.setAttribute(
  1984. "stroke-dasharray",
  1985. element.borderStrokeDasharray
  1986. )
  1987. } else if (element.borderType === "dotted") {
  1988. rightArrow.setAttribute("stroke-dasharray", "1, 3")
  1989. } else if (element.borderType === "dashed") {
  1990. rightArrow.setAttribute("stroke-dasharray", "5, 5")
  1991. }
  1992. }
  1993. }
  1994. svg.appendChild(rightArrow)
  1995. break
  1996. case "leftArrow":
  1997. const leftArrow = document.createElementNS(
  1998. "http://www.w3.org/2000/svg",
  1999. "polygon"
  2000. )
  2001. leftArrow.setAttribute(
  2002. "points",
  2003. `${element.width},${element.height * 0.3} ${element.width * 0.3},${
  2004. element.height * 0.3
  2005. } ` +
  2006. `${element.width * 0.3},0 0,${element.height * 0.5} ` +
  2007. `${element.width * 0.3},${element.height} ${
  2008. element.width * 0.3
  2009. },${element.height * 0.7} ` +
  2010. `${element.width},${element.height * 0.7}`
  2011. )
  2012. // 设置填充色
  2013. setBackground(element, leftArrow)
  2014. // 设置边框
  2015. if (element.borderWidth > 0) {
  2016. leftArrow.setAttribute("stroke", element.borderColor || "#000")
  2017. leftArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2018. // 处理虚线边框
  2019. if (
  2020. element.borderType === "dotted" ||
  2021. element.borderType === "dashed"
  2022. ) {
  2023. if (element.borderStrokeDasharray) {
  2024. leftArrow.setAttribute(
  2025. "stroke-dasharray",
  2026. element.borderStrokeDasharray
  2027. )
  2028. } else if (element.borderType === "dotted") {
  2029. leftArrow.setAttribute("stroke-dasharray", "1, 3")
  2030. } else if (element.borderType === "dashed") {
  2031. leftArrow.setAttribute("stroke-dasharray", "5, 5")
  2032. }
  2033. }
  2034. }
  2035. svg.appendChild(leftArrow)
  2036. break
  2037. case "upArrow":
  2038. const upArrow = document.createElementNS(
  2039. "http://www.w3.org/2000/svg",
  2040. "polygon"
  2041. )
  2042. upArrow.setAttribute(
  2043. "points",
  2044. `${element.width * 0.3},${element.height} ${element.width * 0.3},${
  2045. element.height * 0.3
  2046. } ` +
  2047. `0,${element.height * 0.3} ${element.width * 0.5},0 ` +
  2048. `${element.width},${element.height * 0.3} ${
  2049. element.width * 0.7
  2050. },${element.height * 0.3} ` +
  2051. `${element.width * 0.7},${element.height}`
  2052. )
  2053. // 设置填充色
  2054. setBackground(element, upArrow)
  2055. // 设置边框
  2056. if (element.borderWidth > 0) {
  2057. upArrow.setAttribute("stroke", element.borderColor || "#000")
  2058. upArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2059. // 处理虚线边框
  2060. if (
  2061. element.borderType === "dotted" ||
  2062. element.borderType === "dashed"
  2063. ) {
  2064. if (element.borderStrokeDasharray) {
  2065. upArrow.setAttribute(
  2066. "stroke-dasharray",
  2067. element.borderStrokeDasharray
  2068. )
  2069. } else if (element.borderType === "dotted") {
  2070. upArrow.setAttribute("stroke-dasharray", "1, 3")
  2071. } else if (element.borderType === "dashed") {
  2072. upArrow.setAttribute("stroke-dasharray", "5, 5")
  2073. }
  2074. }
  2075. }
  2076. svg.appendChild(upArrow)
  2077. break
  2078. case "downArrow":
  2079. const downArrow = document.createElementNS(
  2080. "http://www.w3.org/2000/svg",
  2081. "polygon"
  2082. )
  2083. downArrow.setAttribute(
  2084. "points",
  2085. `${element.width * 0.3},0 ${element.width * 0.3},${
  2086. element.height * 0.7
  2087. } ` +
  2088. `0,${element.height * 0.7} ${element.width * 0.5},${
  2089. element.height
  2090. } ` +
  2091. `${element.width},${element.height * 0.7} ${
  2092. element.width * 0.7
  2093. },${element.height * 0.7} ` +
  2094. `${element.width * 0.7},0`
  2095. )
  2096. // 设置填充色
  2097. setBackground(element, downArrow)
  2098. // 设置边框
  2099. if (element.borderWidth > 0) {
  2100. downArrow.setAttribute("stroke", element.borderColor || "#000")
  2101. downArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2102. // 处理虚线边框
  2103. if (
  2104. element.borderType === "dotted" ||
  2105. element.borderType === "dashed"
  2106. ) {
  2107. if (element.borderStrokeDasharray) {
  2108. downArrow.setAttribute(
  2109. "stroke-dasharray",
  2110. element.borderStrokeDasharray
  2111. )
  2112. } else if (element.borderType === "dotted") {
  2113. downArrow.setAttribute("stroke-dasharray", "1, 3")
  2114. } else if (element.borderType === "dashed") {
  2115. downArrow.setAttribute("stroke-dasharray", "5, 5")
  2116. }
  2117. }
  2118. }
  2119. svg.appendChild(downArrow)
  2120. break
  2121. case "leftRightArrow":
  2122. const leftRightArrow = document.createElementNS(
  2123. "http://www.w3.org/2000/svg",
  2124. "polygon"
  2125. )
  2126. leftRightArrow.setAttribute(
  2127. "points",
  2128. `0,${element.height * 0.5} ${element.width * 0.2},${
  2129. element.height * 0.2
  2130. } ` +
  2131. `${element.width * 0.2},${element.height * 0.4} ${
  2132. element.width * 0.8
  2133. },${element.height * 0.4} ` +
  2134. `${element.width * 0.8},${element.height * 0.2} ${
  2135. element.width
  2136. },${element.height * 0.5} ` +
  2137. `${element.width * 0.8},${element.height * 0.8} ${
  2138. element.width * 0.8
  2139. },${element.height * 0.6} ` +
  2140. `${element.width * 0.2},${element.height * 0.6} ${
  2141. element.width * 0.2
  2142. },${element.height * 0.8}`
  2143. )
  2144. // 设置填充色
  2145. setBackground(element, leftRightArrow)
  2146. // 设置边框
  2147. if (element.borderWidth > 0) {
  2148. leftRightArrow.setAttribute("stroke", element.borderColor || "#000")
  2149. leftRightArrow.setAttribute(
  2150. "stroke-width",
  2151. element.borderWidth || 1
  2152. )
  2153. // 处理虚线边框
  2154. if (
  2155. element.borderType === "dotted" ||
  2156. element.borderType === "dashed"
  2157. ) {
  2158. if (element.borderStrokeDasharray) {
  2159. leftRightArrow.setAttribute(
  2160. "stroke-dasharray",
  2161. element.borderStrokeDasharray
  2162. )
  2163. } else if (element.borderType === "dotted") {
  2164. leftRightArrow.setAttribute("stroke-dasharray", "1, 3")
  2165. } else if (element.borderType === "dashed") {
  2166. leftRightArrow.setAttribute("stroke-dasharray", "5, 5")
  2167. }
  2168. }
  2169. }
  2170. svg.appendChild(leftRightArrow)
  2171. break
  2172. case "upDownArrow":
  2173. const upDownArrow = document.createElementNS(
  2174. "http://www.w3.org/2000/svg",
  2175. "polygon"
  2176. )
  2177. upDownArrow.setAttribute(
  2178. "points",
  2179. `${element.width * 0.5},0 ${element.width * 0.3},${
  2180. element.height * 0.2
  2181. } ` +
  2182. `${element.width * 0.4},${element.height * 0.2} ${
  2183. element.width * 0.4
  2184. },${element.height * 0.8} ` +
  2185. `${element.width * 0.3},${element.height * 0.8} ${
  2186. element.width * 0.5
  2187. },${element.height} ` +
  2188. `${element.width * 0.7},${element.height * 0.8} ${
  2189. element.width * 0.6
  2190. },${element.height * 0.8} ` +
  2191. `${element.width * 0.6},${element.height * 0.2} ${
  2192. element.width * 0.7
  2193. },${element.height * 0.2}`
  2194. )
  2195. // 设置填充色
  2196. setBackground(element, upDownArrow)
  2197. // 设置边框
  2198. if (element.borderWidth > 0) {
  2199. upDownArrow.setAttribute("stroke", element.borderColor || "#000")
  2200. upDownArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2201. // 处理虚线边框
  2202. if (
  2203. element.borderType === "dotted" ||
  2204. element.borderType === "dashed"
  2205. ) {
  2206. if (element.borderStrokeDasharray) {
  2207. upDownArrow.setAttribute(
  2208. "stroke-dasharray",
  2209. element.borderStrokeDasharray
  2210. )
  2211. } else if (element.borderType === "dotted") {
  2212. upDownArrow.setAttribute("stroke-dasharray", "1, 3")
  2213. } else if (element.borderType === "dashed") {
  2214. upDownArrow.setAttribute("stroke-dasharray", "5, 5")
  2215. }
  2216. }
  2217. }
  2218. svg.appendChild(upDownArrow)
  2219. break
  2220. case "quadArrow":
  2221. const quadArrow = document.createElementNS(
  2222. "http://www.w3.org/2000/svg",
  2223. "path"
  2224. )
  2225. // 计算缩放比例
  2226. const scale = Math.min(element.width / 167, element.height / 121)
  2227. const offsetX = (element.width - 167 * scale) / 2
  2228. const offsetY = (element.height - 121 * scale) / 2
  2229. // 构建路径数据
  2230. const pathData = `
  2231. M${offsetX},${60.5 * scale + offsetY}
  2232. L${27.225 * scale + offsetX},${33.275 * scale + offsetY}
  2233. L${27.225 * scale + offsetX},${46.8875 * scale + offsetY}
  2234. L${69.8875 * scale + offsetX},${46.8875 * scale + offsetY}
  2235. L${69.8875 * scale + offsetX},${27.225 * scale + offsetY}
  2236. L${56.275 * scale + offsetX},${27.225 * scale + offsetY}
  2237. L${83.5 * scale + offsetX},${offsetY}
  2238. L${110.725 * scale + offsetX},${27.225 * scale + offsetY}
  2239. L${97.1125 * scale + offsetX},${27.225 * scale + offsetY}
  2240. L${97.1125 * scale + offsetX},${46.8875 * scale + offsetY}
  2241. L${139.775 * scale + offsetX},${46.8875 * scale + offsetY}
  2242. L${139.775 * scale + offsetX},${33.275 * scale + offsetY}
  2243. L${167 * scale + offsetX},${60.5 * scale + offsetY}
  2244. L${139.775 * scale + offsetX},${87.725 * scale + offsetY}
  2245. L${139.775 * scale + offsetX},${74.1125 * scale + offsetY}
  2246. L${97.1125 * scale + offsetX},${74.1125 * scale + offsetY}
  2247. L${97.1125 * scale + offsetX},${93.775 * scale + offsetY}
  2248. L${110.725 * scale + offsetX},${93.775 * scale + offsetY}
  2249. L${83.5 * scale + offsetX},${121 * scale + offsetY}
  2250. L${56.275 * scale + offsetX},${93.775 * scale + offsetY}
  2251. L${69.8875 * scale + offsetX},${93.775 * scale + offsetY}
  2252. L${69.8875 * scale + offsetX},${74.1125 * scale + offsetY}
  2253. L${27.225 * scale + offsetX},${74.1125 * scale + offsetY}
  2254. L${27.225 * scale + offsetX},${87.725 * scale + offsetY}
  2255. Z`
  2256. quadArrow.setAttribute("d", pathData)
  2257. // 设置填充色
  2258. setBackground(element, quadArrow)
  2259. // 设置边框
  2260. if (element.borderWidth > 0) {
  2261. quadArrow.setAttribute("stroke", element.borderColor || "#000")
  2262. quadArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2263. quadArrow.setAttribute("stroke-linecap", "butt")
  2264. quadArrow.setAttribute("stroke-linejoin", "round")
  2265. // 处理虚线边框
  2266. if (
  2267. element.borderType === "dotted" ||
  2268. element.borderType === "dashed"
  2269. ) {
  2270. if (element.borderStrokeDasharray) {
  2271. quadArrow.setAttribute(
  2272. "stroke-dasharray",
  2273. element.borderStrokeDasharray
  2274. )
  2275. } else if (element.borderType === "dotted") {
  2276. quadArrow.setAttribute("stroke-dasharray", "1, 3")
  2277. } else if (element.borderType === "dashed") {
  2278. quadArrow.setAttribute("stroke-dasharray", "5, 5")
  2279. }
  2280. }
  2281. }
  2282. svg.appendChild(quadArrow)
  2283. break
  2284. case "leftRightUpArrow":
  2285. const leftRightUpArrow = document.createElementNS(
  2286. "http://www.w3.org/2000/svg",
  2287. "path"
  2288. )
  2289. // 计算缩放比例
  2290. const scale2 = Math.min(element.width / 167, element.height / 121)
  2291. const offsetX2 = (element.width - 167 * scale2) / 2
  2292. const offsetY2 = (element.height - 121 * scale2) / 2
  2293. // 构建路径数据
  2294. const pathData2 = `
  2295. M${offsetX2},${60.5 * scale2 + offsetY2}
  2296. L${27.225 * scale2 + offsetX2},${33.275 * scale2 + offsetY2}
  2297. L${27.225 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
  2298. L${69.8875 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
  2299. L${69.8875 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
  2300. L${56.275 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
  2301. L${83.5 * scale2 + offsetX2},${offsetY2}
  2302. L${110.725 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
  2303. L${97.1125 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
  2304. L${97.1125 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
  2305. L${139.775 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
  2306. L${139.775 * scale2 + offsetX2},${33.275 * scale2 + offsetY2}
  2307. L${167 * scale2 + offsetX2},${60.5 * scale2 + offsetY2}
  2308. L${139.775 * scale2 + offsetX2},${87.725 * scale2 + offsetY2}
  2309. L${139.775 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
  2310. L${97.1125 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
  2311. L${69.8875 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
  2312. L${27.225 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
  2313. L${27.225 * scale2 + offsetX2},${87.725 * scale2 + offsetY2}
  2314. Z`
  2315. leftRightUpArrow.setAttribute("d", pathData2)
  2316. // 设置填充色
  2317. setBackground(element, leftRightUpArrow)
  2318. // 设置边框
  2319. if (element.borderWidth > 0) {
  2320. leftRightUpArrow.setAttribute(
  2321. "stroke",
  2322. element.borderColor || "#000"
  2323. )
  2324. leftRightUpArrow.setAttribute(
  2325. "stroke-width",
  2326. element.borderWidth || 1
  2327. )
  2328. leftRightUpArrow.setAttribute("stroke-linecap", "butt")
  2329. leftRightUpArrow.setAttribute("stroke-linejoin", "round")
  2330. // 处理虚线边框
  2331. if (
  2332. element.borderType === "dotted" ||
  2333. element.borderType === "dashed"
  2334. ) {
  2335. if (element.borderStrokeDasharray) {
  2336. leftRightUpArrow.setAttribute(
  2337. "stroke-dasharray",
  2338. element.borderStrokeDasharray
  2339. )
  2340. } else if (element.borderType === "dotted") {
  2341. leftRightUpArrow.setAttribute("stroke-dasharray", "1, 3")
  2342. } else if (element.borderType === "dashed") {
  2343. leftRightUpArrow.setAttribute("stroke-dasharray", "5, 5")
  2344. }
  2345. }
  2346. }
  2347. svg.appendChild(leftRightUpArrow)
  2348. break
  2349. case "bentArrow":
  2350. const bentArrow = document.createElementNS(
  2351. "http://www.w3.org/2000/svg",
  2352. "path"
  2353. )
  2354. // 构建路径数据
  2355. const pathData3 = `
  2356. M0,${element.height * 0.88}
  2357. L0,${element.height * 0.495}
  2358. A${element.width * 0.385} ${element.height * 0.385} 0 0 1 ${
  2359. element.width * 0.385
  2360. } ${element.height * 0.11}
  2361. L${element.width * 0.67},${element.height * 0.11}
  2362. L${element.width * 0.67},0
  2363. L${element.width * 0.89},${element.height * 0.22}
  2364. L${element.width * 0.67},${element.height * 0.44}
  2365. L${element.width * 0.67},${element.height * 0.33}
  2366. L${element.width * 0.385},${element.height * 0.33}
  2367. A${element.width * 0.165} ${element.height * 0.165} 0 0 0 ${
  2368. element.width * 0.22
  2369. } ${element.height * 0.495}
  2370. L${element.width * 0.22},${element.height * 0.88}
  2371. Z`
  2372. bentArrow.setAttribute("d", pathData3)
  2373. // 设置填充色
  2374. setBackground(element, bentArrow)
  2375. // 设置边框
  2376. if (element.borderWidth > 0) {
  2377. bentArrow.setAttribute("stroke", element.borderColor || "#000")
  2378. bentArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2379. bentArrow.setAttribute("stroke-linecap", "butt")
  2380. bentArrow.setAttribute("stroke-linejoin", "round")
  2381. // 处理虚线边框
  2382. if (
  2383. element.borderType === "dotted" ||
  2384. element.borderType === "dashed"
  2385. ) {
  2386. if (element.borderStrokeDasharray) {
  2387. bentArrow.setAttribute(
  2388. "stroke-dasharray",
  2389. element.borderStrokeDasharray
  2390. )
  2391. } else if (element.borderType === "dotted") {
  2392. bentArrow.setAttribute("stroke-dasharray", "1, 3")
  2393. } else if (element.borderType === "dashed") {
  2394. bentArrow.setAttribute("stroke-dasharray", "5, 5")
  2395. }
  2396. }
  2397. }
  2398. svg.appendChild(bentArrow)
  2399. break
  2400. case "parallelogram":
  2401. const parallelogram = document.createElementNS(
  2402. "http://www.w3.org/2000/svg",
  2403. "polygon"
  2404. )
  2405. parallelogram.setAttribute(
  2406. "points",
  2407. `${element.width * 0.25},0 ${element.width},0 ${
  2408. element.width * 0.75
  2409. },${element.height} 0,${element.height}`
  2410. )
  2411. // 设置填充色
  2412. setBackground(element, parallelogram)
  2413. // 设置边框
  2414. if (element.borderWidth > 0) {
  2415. parallelogram.setAttribute("stroke", element.borderColor || "#000")
  2416. parallelogram.setAttribute("stroke-width", element.borderWidth || 1)
  2417. // 处理虚线边框
  2418. if (
  2419. element.borderType === "dotted" ||
  2420. element.borderType === "dashed"
  2421. ) {
  2422. if (element.borderStrokeDasharray) {
  2423. parallelogram.setAttribute(
  2424. "stroke-dasharray",
  2425. element.borderStrokeDasharray
  2426. )
  2427. } else if (element.borderType === "dotted") {
  2428. parallelogram.setAttribute("stroke-dasharray", "1, 3")
  2429. } else if (element.borderType === "dashed") {
  2430. parallelogram.setAttribute("stroke-dasharray", "5, 5")
  2431. }
  2432. }
  2433. }
  2434. svg.appendChild(parallelogram)
  2435. break
  2436. case "uturnArrow":
  2437. const uturnArrow = document.createElementNS(
  2438. "http://www.w3.org/2000/svg",
  2439. "path"
  2440. )
  2441. // 构建路径数据
  2442. const pathDataUturn = `
  2443. M0,${element.height * 0.745}
  2444. L0,${element.height * 0.179375}
  2445. A${element.width * 0.179375} ${element.height * 0.179375} 0 0 1 ${
  2446. element.width * 0.179375
  2447. },0
  2448. L${element.width * 0.179375},0
  2449. A${element.width * 0.179375} ${element.height * 0.179375} 0 0 1 ${
  2450. element.width * 0.359375
  2451. },${element.height * 0.179375}
  2452. L${element.width * 0.359375},${element.height * 0.205}
  2453. L${element.width * 0.41},${element.height * 0.205}
  2454. L${element.width * 0.3075},${element.height * 0.3075}
  2455. L${element.width * 0.205},${element.height * 0.205}
  2456. L${element.width * 0.25625},${element.height * 0.205}
  2457. L${element.width * 0.25625},${element.height * 0.179375}
  2458. A${element.width * 0.076875} ${element.height * 0.076875} 0 0 0 ${
  2459. element.width * 0.179375
  2460. },${element.height * 0.1025}
  2461. L${element.width * 0.179375},${element.height * 0.1025}
  2462. A${element.width * 0.076875} ${element.height * 0.076875} 0 0 0 ${
  2463. element.width * 0.1025
  2464. },${element.height * 0.179375}
  2465. L${element.width * 0.1025},${element.height * 0.745}
  2466. Z`
  2467. uturnArrow.setAttribute("d", pathDataUturn)
  2468. // 设置填充色
  2469. setBackground(element, uturnArrow)
  2470. // 设置边框
  2471. if (element.borderWidth > 0) {
  2472. uturnArrow.setAttribute("stroke", element.borderColor || "#000")
  2473. uturnArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2474. uturnArrow.setAttribute("stroke-linecap", "butt")
  2475. uturnArrow.setAttribute("stroke-linejoin", "round")
  2476. // 处理虚线边框
  2477. if (
  2478. element.borderType === "dotted" ||
  2479. element.borderType === "dashed"
  2480. ) {
  2481. if (element.borderStrokeDasharray) {
  2482. uturnArrow.setAttribute(
  2483. "stroke-dasharray",
  2484. element.borderStrokeDasharray
  2485. )
  2486. } else if (element.borderType === "dotted") {
  2487. uturnArrow.setAttribute("stroke-dasharray", "1, 3")
  2488. } else if (element.borderType === "dashed") {
  2489. uturnArrow.setAttribute("stroke-dasharray", "5, 5")
  2490. }
  2491. }
  2492. }
  2493. svg.appendChild(uturnArrow)
  2494. break
  2495. case "leftUpArrow":
  2496. const leftUpArrow = document.createElementNS(
  2497. "http://www.w3.org/2000/svg",
  2498. "path"
  2499. )
  2500. // 使用提供的路径数据
  2501. const pathDataLeftUp = `
  2502. M0,${element.height * 0.65}
  2503. L${element.width * 0.15},${element.height * 0.4}
  2504. L${element.width * 0.15},${element.height * 0.55}
  2505. L${element.width * 0.5},${element.height * 0.55}
  2506. L${element.width * 0.5},${element.height * 0.1}
  2507. L${element.width * 0.35},${element.height * 0.1}
  2508. L${element.width * 0.65},0
  2509. L${element.width * 0.85},${element.height * 0.1}
  2510. L${element.width * 0.75},${element.height * 0.1}
  2511. L${element.width * 0.75},${element.height * 0.85}
  2512. L${element.width * 0.15},${element.height * 0.85}
  2513. L${element.width * 0.15},${element.height * 1}
  2514. Z`
  2515. leftUpArrow.setAttribute("d", pathDataLeftUp)
  2516. // 设置填充色
  2517. setBackground(element, leftUpArrow)
  2518. // 设置边框
  2519. if (element.borderWidth > 0) {
  2520. leftUpArrow.setAttribute("stroke", element.borderColor || "#000")
  2521. leftUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2522. leftUpArrow.setAttribute("stroke-linecap", "butt")
  2523. leftUpArrow.setAttribute("stroke-linejoin", "round")
  2524. // 处理虚线边框
  2525. if (
  2526. element.borderType === "dotted" ||
  2527. element.borderType === "dashed"
  2528. ) {
  2529. if (element.borderStrokeDasharray) {
  2530. leftUpArrow.setAttribute(
  2531. "stroke-dasharray",
  2532. element.borderStrokeDasharray
  2533. )
  2534. } else if (element.borderType === "dotted") {
  2535. leftUpArrow.setAttribute("stroke-dasharray", "1, 3")
  2536. } else if (element.borderType === "dashed") {
  2537. leftUpArrow.setAttribute("stroke-dasharray", "5, 5")
  2538. }
  2539. }
  2540. }
  2541. svg.appendChild(leftUpArrow)
  2542. break
  2543. case "bentUpArrow":
  2544. const bentUpArrow = document.createElementNS(
  2545. "http://www.w3.org/2000/svg",
  2546. "path"
  2547. )
  2548. // 构建路径数据,去掉左侧箭头
  2549. // 使用提供的路径数据
  2550. const pathDataBentUp = `
  2551. M0,${element.height * 0.89}
  2552. L0,${element.height * 0.7}
  2553. L${element.width * 0.575},${element.height * 0.7}
  2554. L${element.width * 0.575},${element.height * 0.2}
  2555. L${element.width * 0.46},${element.height * 0.2}
  2556. L${element.width * 0.69},0
  2557. L${element.width * 0.92},${element.height * 0.2}
  2558. L${element.width * 0.805},${element.height * 0.2}
  2559. L${element.width * 0.805},${element.height * 0.89}
  2560. Z`
  2561. bentUpArrow.setAttribute("d", pathDataBentUp)
  2562. // 设置填充色
  2563. setBackground(element, bentUpArrow)
  2564. // 设置边框
  2565. if (element.borderWidth > 0) {
  2566. bentUpArrow.setAttribute("stroke", element.borderColor || "#000")
  2567. bentUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2568. bentUpArrow.setAttribute("stroke-linecap", "butt")
  2569. bentUpArrow.setAttribute("stroke-linejoin", "round")
  2570. // 处理虚线边框
  2571. if (
  2572. element.borderType === "dotted" ||
  2573. element.borderType === "dashed"
  2574. ) {
  2575. if (element.borderStrokeDasharray) {
  2576. bentUpArrow.setAttribute(
  2577. "stroke-dasharray",
  2578. element.borderStrokeDasharray
  2579. )
  2580. } else if (element.borderType === "dotted") {
  2581. bentUpArrow.setAttribute("stroke-dasharray", "1, 3")
  2582. } else if (element.borderType === "dashed") {
  2583. bentUpArrow.setAttribute("stroke-dasharray", "5, 5")
  2584. }
  2585. }
  2586. }
  2587. svg.appendChild(bentUpArrow)
  2588. break
  2589. case "curvedRightArrow":
  2590. const curvedRightArrow = document.createElementNS(
  2591. "http://www.w3.org/2000/svg",
  2592. "path"
  2593. )
  2594. // 使用提供的路径数据
  2595. const pathDataCurvedRight = `
  2596. M${element.width},0
  2597. A${element.width} ${element.height * 0.4} 0 0 0 0 ${
  2598. element.height * 0.4
  2599. }
  2600. L0,${element.height * 0.5}
  2601. A${element.width} ${element.height * 0.4} 0 0 1 ${element.width} ${
  2602. element.height * 0.15
  2603. }
  2604. Z
  2605. M0,${element.height * 0.4}
  2606. A${element.width} ${element.height * 0.4} 0 0 0 ${
  2607. element.width * 0.8
  2608. } ${element.height * 0.8}
  2609. L${element.width * 0.8},${element.height * 0.75}
  2610. L${element.width},${element.height * 0.875}
  2611. L${element.width * 0.8},${element.height * 1}
  2612. L${element.width * 0.8},${element.height * 0.95}
  2613. A${element.width} ${element.height * 0.4} 0 0 1 0 ${
  2614. element.height * 0.5
  2615. }
  2616. Z`
  2617. curvedRightArrow.setAttribute("d", pathDataCurvedRight)
  2618. // 设置填充色
  2619. setBackground(element, curvedRightArrow)
  2620. // 设置边框
  2621. if (element.borderWidth > 0) {
  2622. curvedRightArrow.setAttribute(
  2623. "stroke",
  2624. element.borderColor || "#000"
  2625. )
  2626. curvedRightArrow.setAttribute(
  2627. "stroke-width",
  2628. element.borderWidth || 1
  2629. )
  2630. curvedRightArrow.setAttribute("stroke-linecap", "butt")
  2631. curvedRightArrow.setAttribute("stroke-linejoin", "round")
  2632. // 处理虚线边框
  2633. if (
  2634. element.borderType === "dotted" ||
  2635. element.borderType === "dashed"
  2636. ) {
  2637. if (element.borderStrokeDasharray) {
  2638. curvedRightArrow.setAttribute(
  2639. "stroke-dasharray",
  2640. element.borderStrokeDasharray
  2641. )
  2642. } else if (element.borderType === "dotted") {
  2643. curvedRightArrow.setAttribute("stroke-dasharray", "1, 3")
  2644. } else if (element.borderType === "dashed") {
  2645. curvedRightArrow.setAttribute("stroke-dasharray", "5, 5")
  2646. }
  2647. }
  2648. }
  2649. svg.appendChild(curvedRightArrow)
  2650. break
  2651. case "curvedLeftArrow":
  2652. const curvedLeftArrow = document.createElementNS(
  2653. "http://www.w3.org/2000/svg",
  2654. "path"
  2655. )
  2656. // 定义左弧形箭头的路径数据
  2657. const pathDataCurvedLeft = `
  2658. M0,0
  2659. A${element.width} ${element.height * 0.4} 0 0 1 ${element.width} ${
  2660. element.height * 0.4
  2661. }
  2662. L${element.width},${element.height * 0.55}
  2663. A${element.width} ${element.height * 0.4} 0 0 0 0 ${
  2664. element.height * 0.15
  2665. }
  2666. Z
  2667. M0,${element.height * 0.85}
  2668. L${element.width * 0.25},${element.height * 0.65}
  2669. L${element.width * 0.25},${element.height * 0.75}
  2670. A${element.width} ${element.height * 0.4} 0 0 0 ${element.width} ${
  2671. element.height * 0.4
  2672. }
  2673. L${element.width},${element.height * 0.5}
  2674. L${element.width},${element.height * 0.5}
  2675. A${element.width} ${element.height * 0.4} 0 0 1 ${
  2676. element.width * 0.25
  2677. } ${element.height * 0.9}
  2678. L${element.width * 0.25},${element.height}
  2679. Z`
  2680. curvedLeftArrow.setAttribute("d", pathDataCurvedLeft)
  2681. // 设置填充色
  2682. setBackground(element, curvedLeftArrow)
  2683. // 设置边框
  2684. if (element.borderWidth > 0) {
  2685. curvedLeftArrow.setAttribute(
  2686. "stroke",
  2687. element.borderColor || "#000"
  2688. )
  2689. curvedLeftArrow.setAttribute(
  2690. "stroke-width",
  2691. element.borderWidth || 1
  2692. )
  2693. curvedLeftArrow.setAttribute("stroke-linecap", "butt")
  2694. curvedLeftArrow.setAttribute("stroke-linejoin", "round")
  2695. // 处理虚线边框
  2696. if (
  2697. element.borderType === "dotted" ||
  2698. element.borderType === "dashed"
  2699. ) {
  2700. if (element.borderStrokeDasharray) {
  2701. curvedLeftArrow.setAttribute(
  2702. "stroke-dasharray",
  2703. element.borderStrokeDasharray
  2704. )
  2705. } else if (element.borderType === "dotted") {
  2706. curvedLeftArrow.setAttribute("stroke-dasharray", "1, 3")
  2707. } else if (element.borderType === "dashed") {
  2708. curvedLeftArrow.setAttribute("stroke-dasharray", "5, 5")
  2709. }
  2710. }
  2711. }
  2712. svg.appendChild(curvedLeftArrow)
  2713. break
  2714. case "curvedUpArrow":
  2715. const curvedUpArrow = document.createElementNS(
  2716. "http://www.w3.org/2000/svg",
  2717. "path"
  2718. )
  2719. // 定义上弧形箭头的路径数据
  2720. const pathDataCurvedUp = `
  2721. M${element.width * 0.905},0
  2722. L${element.width * 0.81},${element.height * 0.25}
  2723. L${element.width * 0.857},${element.height * 0.25}
  2724. A${element.width * 0.428} ${element.height} 0 0 1 ${
  2725. element.width * 0.428
  2726. },${element.height}
  2727. L${element.width * 0.522},${element.height}
  2728. A${element.width * 0.428} ${element.height} 0 0 0 ${
  2729. element.width * 0.952
  2730. },${element.height * 0.25}
  2731. L${element.width},${element.height * 0.25}
  2732. Z
  2733. M${element.width * 0.094},0
  2734. L0,0
  2735. A${element.width * 0.428} ${element.height} 0 0 0 ${
  2736. element.width * 0.428
  2737. },${element.height}
  2738. L${element.width * 0.522},${element.height}
  2739. A${element.width * 0.428} ${element.height} 0 0 1 ${
  2740. element.width * 0.094
  2741. },0
  2742. Z`
  2743. curvedUpArrow.setAttribute("d", pathDataCurvedUp)
  2744. // 设置填充色
  2745. setBackground(element, curvedUpArrow)
  2746. // 设置边框
  2747. if (element.borderWidth > 0) {
  2748. curvedUpArrow.setAttribute("stroke", element.borderColor || "#000")
  2749. curvedUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
  2750. curvedUpArrow.setAttribute("stroke-linecap", "butt")
  2751. curvedUpArrow.setAttribute("stroke-linejoin", "round")
  2752. // 处理虚线边框
  2753. if (
  2754. element.borderType === "dotted" ||
  2755. element.borderType === "dashed"
  2756. ) {
  2757. if (element.borderStrokeDasharray) {
  2758. curvedUpArrow.setAttribute(
  2759. "stroke-dasharray",
  2760. element.borderStrokeDasharray
  2761. )
  2762. } else if (element.borderType === "dotted") {
  2763. curvedUpArrow.setAttribute("stroke-dasharray", "1, 3")
  2764. } else if (element.borderType === "dashed") {
  2765. curvedUpArrow.setAttribute("stroke-dasharray", "5, 5")
  2766. }
  2767. }
  2768. }
  2769. svg.appendChild(curvedUpArrow)
  2770. break
  2771. case "curvedDownArrow":
  2772. const curvedDownArrow = document.createElementNS(
  2773. "http://www.w3.org/2000/svg",
  2774. "path"
  2775. )
  2776. // 定义下弧形箭头的路径数据
  2777. const pathDataCurvedDown = `
  2778. M0,${element.height}
  2779. L${element.width * 0.16},${element.height}
  2780. A${element.width * 0.46} ${element.height} 0 0 1 ${
  2781. element.width * 0.62
  2782. },0
  2783. L${element.width * 0.46},0
  2784. A${element.width * 0.46} ${element.height} 0 0 0 0,${element.height}
  2785. Z
  2786. M${element.width},${element.height}
  2787. L${element.width * 0.84},${element.height * 0.75}
  2788. L${element.width * 0.92},${element.height * 0.75}
  2789. A${element.width * 0.46} ${element.height} 0 0 0 ${
  2790. element.width * 0.46
  2791. },0
  2792. L${element.width * 0.62},0
  2793. A${element.width * 0.46} ${element.height} 0 0 1 ${
  2794. element.width * 1.08
  2795. },${element.height * 0.75}
  2796. L${element.width * 1.16},${element.height * 0.75}
  2797. Z`
  2798. curvedDownArrow.setAttribute("d", pathDataCurvedDown)
  2799. // 设置填充色
  2800. setBackground(element, curvedDownArrow)
  2801. // 设置边框
  2802. if (element.borderWidth > 0) {
  2803. curvedDownArrow.setAttribute(
  2804. "stroke",
  2805. element.borderColor || "#000"
  2806. )
  2807. curvedDownArrow.setAttribute(
  2808. "stroke-width",
  2809. element.borderWidth || 1
  2810. )
  2811. curvedDownArrow.setAttribute("stroke-linecap", "butt")
  2812. curvedDownArrow.setAttribute("stroke-linejoin", "round")
  2813. // 处理虚线边框
  2814. if (
  2815. element.borderType === "dotted" ||
  2816. element.borderType === "dashed"
  2817. ) {
  2818. if (element.borderStrokeDasharray) {
  2819. curvedDownArrow.setAttribute(
  2820. "stroke-dasharray",
  2821. element.borderStrokeDasharray
  2822. )
  2823. } else if (element.borderType === "dotted") {
  2824. curvedDownArrow.setAttribute("stroke-dasharray", "1, 3")
  2825. } else if (element.borderType === "dashed") {
  2826. curvedDownArrow.setAttribute("stroke-dasharray", "5, 5")
  2827. }
  2828. }
  2829. }
  2830. svg.appendChild(curvedDownArrow)
  2831. break
  2832. case "stripedRightArrow":
  2833. const stripedRightArrow = document.createElementNS(
  2834. "http://www.w3.org/2000/svg",
  2835. "g"
  2836. )
  2837. // 主箭头部分
  2838. const mainArrow = document.createElementNS(
  2839. "http://www.w3.org/2000/svg",
  2840. "path"
  2841. )
  2842. mainArrow.setAttribute(
  2843. "d",
  2844. `M${element.width * 0.062},${element.height * 0.25}
  2845. L${element.width * 0.8},${element.height * 0.25}
  2846. L${element.width * 0.8},0
  2847. L${element.width},${element.height * 0.5}
  2848. L${element.width * 0.8},${element.height}
  2849. L${element.width * 0.8},${element.height * 0.75}
  2850. L${element.width * 0.062},${element.height * 0.75}
  2851. Z`
  2852. )
  2853. // 第一条尾部条纹
  2854. const stripe1 = document.createElementNS(
  2855. "http://www.w3.org/2000/svg",
  2856. "path"
  2857. )
  2858. stripe1.setAttribute(
  2859. "d",
  2860. `M0,${element.height * 0.25}
  2861. L${element.width * 0.012},${element.height * 0.25}
  2862. L${element.width * 0.012},${element.height * 0.75}
  2863. L0,${element.height * 0.75}
  2864. Z`
  2865. )
  2866. // 第二条尾部条纹
  2867. const stripe2 = document.createElementNS(
  2868. "http://www.w3.org/2000/svg",
  2869. "path"
  2870. )
  2871. stripe2.setAttribute(
  2872. "d",
  2873. `M${element.width * 0.025},${element.height * 0.25}
  2874. L${element.width * 0.049},${element.height * 0.25}
  2875. L${element.width * 0.049},${element.height * 0.75}
  2876. L${element.width * 0.025},${element.height * 0.75}
  2877. Z`
  2878. )
  2879. // 设置填充色
  2880. setBackground(element, mainArrow)
  2881. setBackground(element, stripe1)
  2882. setBackground(element, stripe2)
  2883. // 设置边框
  2884. if (element.borderWidth > 0) {
  2885. ;[mainArrow, stripe1, stripe2].forEach((path) => {
  2886. path.setAttribute("stroke", element.borderColor || "#000")
  2887. path.setAttribute("stroke-width", element.borderWidth || 1)
  2888. path.setAttribute("stroke-linecap", "butt")
  2889. path.setAttribute("stroke-linejoin", "round")
  2890. // 处理虚线边框
  2891. if (
  2892. element.borderType === "dotted" ||
  2893. element.borderType === "dashed"
  2894. ) {
  2895. if (element.borderStrokeDasharray) {
  2896. path.setAttribute(
  2897. "stroke-dasharray",
  2898. element.borderStrokeDasharray
  2899. )
  2900. } else if (element.borderType === "dotted") {
  2901. path.setAttribute("stroke-dasharray", "1, 3")
  2902. } else if (element.borderType === "dashed") {
  2903. path.setAttribute("stroke-dasharray", "5, 5")
  2904. }
  2905. }
  2906. })
  2907. }
  2908. stripedRightArrow.appendChild(mainArrow)
  2909. stripedRightArrow.appendChild(stripe1)
  2910. stripedRightArrow.appendChild(stripe2)
  2911. svg.appendChild(stripedRightArrow)
  2912. break
  2913. case "rightArrowCallout":
  2914. const rightArrowCallout = document.createElementNS(
  2915. "http://www.w3.org/2000/svg",
  2916. "path"
  2917. )
  2918. rightArrowCallout.setAttribute(
  2919. "d",
  2920. `M0,0
  2921. L${element.width * 0.44},0
  2922. L${element.width * 0.44},${element.height * 0.375}
  2923. L${element.width * 0.79},${element.height * 0.375}
  2924. L${element.width * 0.79},${element.height * 0.25}
  2925. L${element.width},${element.height * 0.5}
  2926. L${element.width * 0.79},${element.height * 0.75}
  2927. L${element.width * 0.79},${element.height * 0.625}
  2928. L${element.width * 0.44},${element.height * 0.625}
  2929. L${element.width * 0.44},${element.height}
  2930. L0,${element.height}
  2931. Z`
  2932. )
  2933. // 设置填充色
  2934. setBackground(element, rightArrowCallout)
  2935. // 设置边框
  2936. if (element.borderWidth > 0) {
  2937. rightArrowCallout.setAttribute(
  2938. "stroke",
  2939. element.borderColor || "#000"
  2940. )
  2941. rightArrowCallout.setAttribute(
  2942. "stroke-width",
  2943. element.borderWidth || 1
  2944. )
  2945. rightArrowCallout.setAttribute("stroke-linecap", "butt")
  2946. rightArrowCallout.setAttribute("stroke-linejoin", "round")
  2947. // 处理虚线边框
  2948. if (
  2949. element.borderType === "dotted" ||
  2950. element.borderType === "dashed"
  2951. ) {
  2952. if (element.borderStrokeDasharray) {
  2953. rightArrowCallout.setAttribute(
  2954. "stroke-dasharray",
  2955. element.borderStrokeDasharray
  2956. )
  2957. } else if (element.borderType === "dotted") {
  2958. rightArrowCallout.setAttribute("stroke-dasharray", "1, 3")
  2959. } else if (element.borderType === "dashed") {
  2960. rightArrowCallout.setAttribute("stroke-dasharray", "5, 5")
  2961. }
  2962. }
  2963. }
  2964. svg.appendChild(rightArrowCallout)
  2965. break
  2966. case "leftRightArrowCallout":
  2967. const leftRightArrowCallout = document.createElementNS(
  2968. "http://www.w3.org/2000/svg",
  2969. "path"
  2970. )
  2971. leftRightArrowCallout.setAttribute(
  2972. "d",
  2973. `M0,${element.height * 0.5}
  2974. L${element.width * 0.139},${element.height * 0.25}
  2975. L${element.width * 0.139},${element.height * 0.375}
  2976. L${element.width * 0.364},${element.height * 0.375}
  2977. L${element.width * 0.364},0
  2978. L${element.width * 0.636},0
  2979. L${element.width * 0.636},${element.height * 0.375}
  2980. L${element.width * 0.861},${element.height * 0.375}
  2981. L${element.width * 0.861},${element.height * 0.25}
  2982. L${element.width},${element.height * 0.5}
  2983. L${element.width * 0.861},${element.height * 0.75}
  2984. L${element.width * 0.861},${element.height * 0.625}
  2985. L${element.width * 0.636},${element.height * 0.625}
  2986. L${element.width * 0.636},${element.height}
  2987. L${element.width * 0.364},${element.height}
  2988. L${element.width * 0.364},${element.height * 0.625}
  2989. L${element.width * 0.139},${element.height * 0.625}
  2990. L${element.width * 0.139},${element.height * 0.75}
  2991. Z`
  2992. )
  2993. // 设置填充色
  2994. setBackground(element, leftRightArrowCallout)
  2995. // 设置边框
  2996. if (element.borderWidth > 0) {
  2997. leftRightArrowCallout.setAttribute(
  2998. "stroke",
  2999. element.borderColor || "#000"
  3000. )
  3001. leftRightArrowCallout.setAttribute(
  3002. "stroke-width",
  3003. element.borderWidth || 1
  3004. )
  3005. leftRightArrowCallout.setAttribute("stroke-linecap", "butt")
  3006. leftRightArrowCallout.setAttribute("stroke-linejoin", "round")
  3007. // 处理虚线边框
  3008. if (
  3009. element.borderType === "dotted" ||
  3010. element.borderType === "dashed"
  3011. ) {
  3012. if (element.borderStrokeDasharray) {
  3013. leftRightArrowCallout.setAttribute(
  3014. "stroke-dasharray",
  3015. element.borderStrokeDasharray
  3016. )
  3017. } else if (element.borderType === "dotted") {
  3018. leftRightArrowCallout.setAttribute("stroke-dasharray", "1, 3")
  3019. } else if (element.borderType === "dashed") {
  3020. leftRightArrowCallout.setAttribute("stroke-dasharray", "5, 5")
  3021. }
  3022. }
  3023. }
  3024. svg.appendChild(leftRightArrowCallout)
  3025. break
  3026. case "quadArrowCallout":
  3027. const quadArrowCallout = document.createElementNS(
  3028. "http://www.w3.org/2000/svg",
  3029. "path"
  3030. )
  3031. quadArrowCallout.setAttribute(
  3032. "d",
  3033. `M0,${element.height * 0.5}
  3034. L${element.width * 0.096},${element.height * 0.315}
  3035. L${element.width * 0.096},${element.height * 0.407}
  3036. L${element.width * 0.26},${element.height * 0.407}
  3037. L${element.width * 0.26},${element.height * 0.259}
  3038. L${element.width * 0.453},${element.height * 0.259}
  3039. L${element.width * 0.453},${element.height * 0.185}
  3040. L${element.width * 0.405},${element.height * 0.185}
  3041. L${element.width * 0.5},0
  3042. L${element.width * 0.595},${element.height * 0.185}
  3043. L${element.width * 0.547},${element.height * 0.185}
  3044. L${element.width * 0.547},${element.height * 0.259}
  3045. L${element.width * 0.74},${element.height * 0.259}
  3046. L${element.width * 0.74},${element.height * 0.407}
  3047. L${element.width * 0.904},${element.height * 0.407}
  3048. L${element.width * 0.904},${element.height * 0.315}
  3049. L${element.width},${element.height * 0.5}
  3050. L${element.width * 0.904},${element.height * 0.685}
  3051. L${element.width * 0.904},${element.height * 0.593}
  3052. L${element.width * 0.74},${element.height * 0.593}
  3053. L${element.width * 0.74},${element.height * 0.741}
  3054. L${element.width * 0.547},${element.height * 0.741}
  3055. L${element.width * 0.547},${element.height * 0.815}
  3056. L${element.width * 0.595},${element.height * 0.815}
  3057. L${element.width * 0.5},${element.height}
  3058. L${element.width * 0.405},${element.height * 0.815}
  3059. L${element.width * 0.453},${element.height * 0.815}
  3060. L${element.width * 0.453},${element.height * 0.741}
  3061. L${element.width * 0.26},${element.height * 0.741}
  3062. L${element.width * 0.26},${element.height * 0.593}
  3063. L${element.width * 0.096},${element.height * 0.593}
  3064. L${element.width * 0.096},${element.height * 0.685}
  3065. Z`
  3066. )
  3067. // 设置填充色
  3068. setBackground(element, quadArrowCallout)
  3069. // 设置边框
  3070. if (element.borderWidth > 0) {
  3071. quadArrowCallout.setAttribute(
  3072. "stroke",
  3073. element.borderColor || "#000"
  3074. )
  3075. quadArrowCallout.setAttribute(
  3076. "stroke-width",
  3077. element.borderWidth || 1
  3078. )
  3079. quadArrowCallout.setAttribute("stroke-linecap", "butt")
  3080. quadArrowCallout.setAttribute("stroke-linejoin", "round")
  3081. // 处理虚线边框
  3082. if (
  3083. element.borderType === "dotted" ||
  3084. element.borderType === "dashed"
  3085. ) {
  3086. if (element.borderStrokeDasharray) {
  3087. quadArrowCallout.setAttribute(
  3088. "stroke-dasharray",
  3089. element.borderStrokeDasharray
  3090. )
  3091. } else if (element.borderType === "dotted") {
  3092. quadArrowCallout.setAttribute("stroke-dasharray", "1, 3")
  3093. } else if (element.borderType === "dashed") {
  3094. quadArrowCallout.setAttribute("stroke-dasharray", "5, 5")
  3095. }
  3096. }
  3097. }
  3098. svg.appendChild(quadArrowCallout)
  3099. break
  3100. case "leftArrowCallout":
  3101. const leftArrowCallout = document.createElementNS(
  3102. "http://www.w3.org/2000/svg",
  3103. "path"
  3104. )
  3105. leftArrowCallout.setAttribute(
  3106. "d",
  3107. `M0,${element.height * 0.5}
  3108. L${element.width * 0.183},${element.height * 0.25}
  3109. L${element.width * 0.183},${element.height * 0.375}
  3110. L${element.width * 0.35},${element.height * 0.375}
  3111. L${element.width * 0.35},0
  3112. L${element.width},0
  3113. L${element.width},${element.height}
  3114. L${element.width * 0.35},${element.height}
  3115. L${element.width * 0.35},${element.height * 0.625}
  3116. L${element.width * 0.183},${element.height * 0.625}
  3117. L${element.width * 0.183},${element.height * 0.75}
  3118. Z`
  3119. )
  3120. // 设置填充色
  3121. setBackground(element, leftArrowCallout)
  3122. // 设置边框
  3123. if (element.borderWidth > 0) {
  3124. leftArrowCallout.setAttribute(
  3125. "stroke",
  3126. element.borderColor || "#000"
  3127. )
  3128. leftArrowCallout.setAttribute(
  3129. "stroke-width",
  3130. element.borderWidth || 1
  3131. )
  3132. leftArrowCallout.setAttribute("stroke-linecap", "butt")
  3133. leftArrowCallout.setAttribute("stroke-linejoin", "round")
  3134. // 处理虚线边框
  3135. if (
  3136. element.borderType === "dotted" ||
  3137. element.borderType === "dashed"
  3138. ) {
  3139. if (element.borderStrokeDasharray) {
  3140. leftArrowCallout.setAttribute(
  3141. "stroke-dasharray",
  3142. element.borderStrokeDasharray
  3143. )
  3144. } else if (element.borderType === "dotted") {
  3145. leftArrowCallout.setAttribute("stroke-dasharray", "1, 3")
  3146. } else if (element.borderType === "dashed") {
  3147. leftArrowCallout.setAttribute("stroke-dasharray", "5, 5")
  3148. }
  3149. }
  3150. }
  3151. svg.appendChild(leftArrowCallout)
  3152. break
  3153. case "upArrowCallout":
  3154. const upArrowCallout = document.createElementNS(
  3155. "http://www.w3.org/2000/svg",
  3156. "path"
  3157. )
  3158. upArrowCallout.setAttribute(
  3159. "d",
  3160. `M0,${element.height * 0.35}
  3161. L${element.width * 0.41},${element.height * 0.35}
  3162. L${element.width * 0.41},${element.height * 0.25}
  3163. L${element.width * 0.32},${element.height * 0.25}
  3164. L${element.width * 0.5},0
  3165. L${element.width * 0.68},${element.height * 0.25}
  3166. L${element.width * 0.59},${element.height * 0.25}
  3167. L${element.width * 0.59},${element.height * 0.35}
  3168. L${element.width},${element.height * 0.35}
  3169. L${element.width},${element.height}
  3170. L0,${element.height}
  3171. Z`
  3172. )
  3173. // 设置填充色
  3174. setBackground(element, upArrowCallout)
  3175. // 设置边框
  3176. if (element.borderWidth > 0) {
  3177. upArrowCallout.setAttribute("stroke", element.borderColor || "#000")
  3178. upArrowCallout.setAttribute(
  3179. "stroke-width",
  3180. element.borderWidth || 1
  3181. )
  3182. upArrowCallout.setAttribute("stroke-linecap", "butt")
  3183. upArrowCallout.setAttribute("stroke-linejoin", "round")
  3184. // 处理虚线边框
  3185. if (
  3186. element.borderType === "dotted" ||
  3187. element.borderType === "dashed"
  3188. ) {
  3189. if (element.borderStrokeDasharray) {
  3190. upArrowCallout.setAttribute(
  3191. "stroke-dasharray",
  3192. element.borderStrokeDasharray
  3193. )
  3194. } else if (element.borderType === "dotted") {
  3195. upArrowCallout.setAttribute("stroke-dasharray", "1, 3")
  3196. } else if (element.borderType === "dashed") {
  3197. upArrowCallout.setAttribute("stroke-dasharray", "5, 5")
  3198. }
  3199. }
  3200. }
  3201. svg.appendChild(upArrowCallout)
  3202. break
  3203. case "notchedRightArrow":
  3204. const notchedRightArrow = document.createElementNS(
  3205. "http://www.w3.org/2000/svg",
  3206. "path"
  3207. )
  3208. notchedRightArrow.setAttribute(
  3209. "d",
  3210. `M0,${element.height * 0.25}
  3211. L${element.width * 0.83},${element.height * 0.25}
  3212. L${element.width * 0.83},0
  3213. L${element.width},${element.height * 0.5}
  3214. L${element.width * 0.83},${element.height}
  3215. L${element.width * 0.83},${element.height * 0.75}
  3216. L0,${element.height * 0.75}
  3217. L${element.width * 0.086},${element.height * 0.5}
  3218. Z`
  3219. )
  3220. // 设置填充色
  3221. setBackground(element, notchedRightArrow)
  3222. // 设置边框
  3223. if (element.borderWidth > 0) {
  3224. notchedRightArrow.setAttribute(
  3225. "stroke",
  3226. element.borderColor || "#000"
  3227. )
  3228. notchedRightArrow.setAttribute(
  3229. "stroke-width",
  3230. element.borderWidth || 1
  3231. )
  3232. notchedRightArrow.setAttribute("stroke-linecap", "butt")
  3233. notchedRightArrow.setAttribute("stroke-linejoin", "round")
  3234. // 处理虚线边框
  3235. if (
  3236. element.borderType === "dotted" ||
  3237. element.borderType === "dashed"
  3238. ) {
  3239. if (element.borderStrokeDasharray) {
  3240. notchedRightArrow.setAttribute(
  3241. "stroke-dasharray",
  3242. element.borderStrokeDasharray
  3243. )
  3244. } else if (element.borderType === "dotted") {
  3245. notchedRightArrow.setAttribute("stroke-dasharray", "1, 3")
  3246. } else if (element.borderType === "dashed") {
  3247. notchedRightArrow.setAttribute("stroke-dasharray", "5, 5")
  3248. }
  3249. }
  3250. }
  3251. svg.appendChild(notchedRightArrow)
  3252. break
  3253. case "homePlate":
  3254. const homePlate = document.createElementNS(
  3255. "http://www.w3.org/2000/svg",
  3256. "path"
  3257. )
  3258. homePlate.setAttribute(
  3259. "d",
  3260. `M0,0
  3261. L${element.width * 0.925},0
  3262. L${element.width},${element.height * 0.5}
  3263. L${element.width * 0.925},${element.height}
  3264. L0,${element.height}
  3265. Z`
  3266. )
  3267. // 设置填充色
  3268. setBackground(element, homePlate)
  3269. // 设置边框
  3270. if (element.borderWidth > 0) {
  3271. homePlate.setAttribute("stroke", element.borderColor || "#000")
  3272. homePlate.setAttribute("stroke-width", element.borderWidth || 1)
  3273. homePlate.setAttribute("stroke-linecap", "butt")
  3274. homePlate.setAttribute("stroke-linejoin", "round")
  3275. // 处理虚线边框
  3276. if (
  3277. element.borderType === "dotted" ||
  3278. element.borderType === "dashed"
  3279. ) {
  3280. if (element.borderStrokeDasharray) {
  3281. homePlate.setAttribute(
  3282. "stroke-dasharray",
  3283. element.borderStrokeDasharray
  3284. )
  3285. } else if (element.borderType === "dotted") {
  3286. homePlate.setAttribute("stroke-dasharray", "1, 3")
  3287. } else if (element.borderType === "dashed") {
  3288. homePlate.setAttribute("stroke-dasharray", "5, 5")
  3289. }
  3290. }
  3291. }
  3292. svg.appendChild(homePlate)
  3293. break
  3294. case "rightTriangle":
  3295. const rightTriangle = document.createElementNS(
  3296. "http://www.w3.org/2000/svg",
  3297. "polygon"
  3298. )
  3299. rightTriangle.setAttribute(
  3300. "points",
  3301. `0,0 ${element.width},${element.height} 0,${element.height}`
  3302. )
  3303. // 设置填充色
  3304. setBackground(element, rightTriangle)
  3305. // 设置边框
  3306. if (element.borderWidth > 0) {
  3307. rightTriangle.setAttribute("stroke", element.borderColor || "#000")
  3308. rightTriangle.setAttribute("stroke-width", element.borderWidth || 1)
  3309. // 处理虚线边框
  3310. if (
  3311. element.borderType === "dotted" ||
  3312. element.borderType === "dashed"
  3313. ) {
  3314. if (element.borderStrokeDasharray) {
  3315. rightTriangle.setAttribute(
  3316. "stroke-dasharray",
  3317. element.borderStrokeDasharray
  3318. )
  3319. } else if (element.borderType === "dotted") {
  3320. rightTriangle.setAttribute("stroke-dasharray", "1, 3")
  3321. } else if (element.borderType === "dashed") {
  3322. rightTriangle.setAttribute("stroke-dasharray", "5, 5")
  3323. }
  3324. }
  3325. }
  3326. svg.appendChild(rightTriangle)
  3327. break
  3328. case "semiCircle":
  3329. const semiCircle = document.createElementNS(
  3330. "http://www.w3.org/2000/svg",
  3331. "path"
  3332. )
  3333. semiCircle.setAttribute(
  3334. "d",
  3335. `M0,${element.height} A${element.width / 2},${
  3336. element.height
  3337. } 0 0,1 ${element.width},${element.height} Z`
  3338. )
  3339. // 设置填充色
  3340. setBackground(element, semiCircle)
  3341. // 设置边框
  3342. if (element.borderWidth > 0) {
  3343. semiCircle.setAttribute("stroke", element.borderColor || "#000")
  3344. semiCircle.setAttribute("stroke-width", element.borderWidth || 1)
  3345. // 处理虚线边框
  3346. if (
  3347. element.borderType === "dotted" ||
  3348. element.borderType === "dashed"
  3349. ) {
  3350. if (element.borderStrokeDasharray) {
  3351. semiCircle.setAttribute(
  3352. "stroke-dasharray",
  3353. element.borderStrokeDasharray
  3354. )
  3355. } else if (element.borderType === "dotted") {
  3356. semiCircle.setAttribute("stroke-dasharray", "1, 3")
  3357. } else if (element.borderType === "dashed") {
  3358. semiCircle.setAttribute("stroke-dasharray", "5, 5")
  3359. }
  3360. }
  3361. }
  3362. svg.appendChild(semiCircle)
  3363. break
  3364. case "star":
  3365. const star = document.createElementNS(
  3366. "http://www.w3.org/2000/svg",
  3367. "polygon"
  3368. )
  3369. const cx = element.width / 2
  3370. const cy = element.height / 2
  3371. const outerRadius = Math.min(element.width, element.height) / 2
  3372. const innerRadius = outerRadius * 0.4
  3373. let starPoints = ""
  3374. for (let i = 0; i < 10; i++) {
  3375. const radius = i % 2 === 0 ? outerRadius : innerRadius
  3376. const angle = (Math.PI * i) / 5
  3377. const x = cx + radius * Math.sin(angle)
  3378. const y = cy - radius * Math.cos(angle)
  3379. starPoints += `${x},${y} `
  3380. }
  3381. star.setAttribute("points", starPoints.trim())
  3382. // 设置填充色
  3383. setBackground(element, star)
  3384. // 设置边框
  3385. if (element.borderWidth > 0) {
  3386. star.setAttribute("stroke", element.borderColor || "#000")
  3387. star.setAttribute("stroke-width", element.borderWidth || 1)
  3388. // 处理虚线边框
  3389. if (
  3390. element.borderType === "dotted" ||
  3391. element.borderType === "dashed"
  3392. ) {
  3393. if (element.borderStrokeDasharray) {
  3394. star.setAttribute(
  3395. "stroke-dasharray",
  3396. element.borderStrokeDasharray
  3397. )
  3398. } else if (element.borderType === "dotted") {
  3399. star.setAttribute("stroke-dasharray", "1, 3")
  3400. } else if (element.borderType === "dashed") {
  3401. star.setAttribute("stroke-dasharray", "5, 5")
  3402. }
  3403. }
  3404. }
  3405. svg.appendChild(star)
  3406. break
  3407. case "cross":
  3408. const cross = document.createElementNS(
  3409. "http://www.w3.org/2000/svg",
  3410. "polygon"
  3411. )
  3412. cross.setAttribute(
  3413. "points",
  3414. `${element.width * 0.35},0 ${element.width * 0.65},0 ${
  3415. element.width * 0.65
  3416. },${element.height * 0.35} ` +
  3417. `${element.width},${element.height * 0.35} ${element.width},${
  3418. element.height * 0.65
  3419. } ` +
  3420. `${element.width * 0.65},${element.height * 0.65} ${
  3421. element.width * 0.65
  3422. },${element.height} ` +
  3423. `${element.width * 0.35},${element.height} ${
  3424. element.width * 0.35
  3425. },${element.height * 0.65} ` +
  3426. `0,${element.height * 0.65} 0,${element.height * 0.35} ${
  3427. element.width * 0.35
  3428. },${element.height * 0.35}`
  3429. )
  3430. // 设置填充色
  3431. setBackground(element, cross)
  3432. // 设置边框
  3433. if (element.borderWidth > 0) {
  3434. cross.setAttribute("stroke", element.borderColor || "#000")
  3435. cross.setAttribute("stroke-width", element.borderWidth || 1)
  3436. // 处理虚线边框
  3437. if (
  3438. element.borderType === "dotted" ||
  3439. element.borderType === "dashed"
  3440. ) {
  3441. if (element.borderStrokeDasharray) {
  3442. cross.setAttribute(
  3443. "stroke-dasharray",
  3444. element.borderStrokeDasharray
  3445. )
  3446. } else if (element.borderType === "dotted") {
  3447. cross.setAttribute("stroke-dasharray", "1, 3")
  3448. } else if (element.borderType === "dashed") {
  3449. cross.setAttribute("stroke-dasharray", "5, 5")
  3450. }
  3451. }
  3452. }
  3453. svg.appendChild(cross)
  3454. break
  3455. case "chevron":
  3456. const chevron = document.createElementNS(
  3457. "http://www.w3.org/2000/svg",
  3458. "polygon"
  3459. )
  3460. chevron.setAttribute(
  3461. "points",
  3462. `${element.width * 0.5},0 ${element.width},${
  3463. element.height * 0.5
  3464. } ` +
  3465. `${element.width * 0.5},${element.height} ` +
  3466. `0,${element.height} ${element.width * 0.5},${
  3467. element.height * 0.5
  3468. } 0,0`
  3469. )
  3470. // 设置填充色
  3471. setBackground(element, chevron)
  3472. // 设置边框
  3473. if (element.borderWidth > 0) {
  3474. chevron.setAttribute("stroke", element.borderColor || "#000")
  3475. chevron.setAttribute("stroke-width", element.borderWidth || 1)
  3476. // 处理虚线边框
  3477. if (
  3478. element.borderType === "dotted" ||
  3479. element.borderType === "dashed"
  3480. ) {
  3481. if (element.borderStrokeDasharray) {
  3482. chevron.setAttribute(
  3483. "stroke-dasharray",
  3484. element.borderStrokeDasharray
  3485. )
  3486. } else if (element.borderType === "dotted") {
  3487. chevron.setAttribute("stroke-dasharray", "1, 3")
  3488. } else if (element.borderType === "dashed") {
  3489. chevron.setAttribute("stroke-dasharray", "5, 5")
  3490. }
  3491. }
  3492. }
  3493. svg.appendChild(chevron)
  3494. break
  3495. case "frame":
  3496. // 创建外框和内框
  3497. const outerRect = document.createElementNS(
  3498. "http://www.w3.org/2000/svg",
  3499. "rect"
  3500. )
  3501. outerRect.setAttribute("x", 0)
  3502. outerRect.setAttribute("y", 0)
  3503. outerRect.setAttribute("width", element.width)
  3504. outerRect.setAttribute("height", element.height)
  3505. const innerRect = document.createElementNS(
  3506. "http://www.w3.org/2000/svg",
  3507. "rect"
  3508. )
  3509. const frameWidth = element.width / 10
  3510. innerRect.setAttribute("x", frameWidth)
  3511. innerRect.setAttribute("y", frameWidth)
  3512. innerRect.setAttribute("width", element.width - frameWidth * 2)
  3513. innerRect.setAttribute("height", element.height - frameWidth * 2)
  3514. // 设置填充色
  3515. setBackground(element, outerRect)
  3516. innerRect.setAttribute("fill", "white") // 内框为白色
  3517. // 设置边框
  3518. if (element.borderWidth > 0) {
  3519. outerRect.setAttribute("stroke", element.borderColor || "#000")
  3520. outerRect.setAttribute("stroke-width", element.borderWidth || 1)
  3521. // 处理虚线边框
  3522. if (
  3523. element.borderType === "dotted" ||
  3524. element.borderType === "dashed"
  3525. ) {
  3526. if (element.borderStrokeDasharray) {
  3527. outerRect.setAttribute(
  3528. "stroke-dasharray",
  3529. element.borderStrokeDasharray
  3530. )
  3531. } else if (element.borderType === "dotted") {
  3532. outerRect.setAttribute("stroke-dasharray", "1, 3")
  3533. } else if (element.borderType === "dashed") {
  3534. outerRect.setAttribute("stroke-dasharray", "5, 5")
  3535. }
  3536. }
  3537. }
  3538. svg.appendChild(outerRect)
  3539. svg.appendChild(innerRect)
  3540. break
  3541. case "cloud":
  3542. // 使用路径绘制云形
  3543. const cloud = document.createElementNS(
  3544. "http://www.w3.org/2000/svg",
  3545. "path"
  3546. )
  3547. const w = element.width
  3548. const h = element.height
  3549. cloud.setAttribute(
  3550. "d",
  3551. `M${w * 0.2},${h * 0.6} ` +
  3552. `C${w * 0.05},${h * 0.6} ${w * 0.05},${h * 0.3} ${w * 0.2},${
  3553. h * 0.3
  3554. } ` +
  3555. `C${w * 0.2},${h * 0.1} ${w * 0.45},${h * 0.1} ${w * 0.5},${
  3556. h * 0.3
  3557. } ` +
  3558. `C${w * 0.55},${h * 0.1} ${w * 0.8},${h * 0.1} ${w * 0.8},${
  3559. h * 0.3
  3560. } ` +
  3561. `C${w * 0.95},${h * 0.3} ${w * 0.95},${h * 0.6} ${w * 0.8},${
  3562. h * 0.6
  3563. } ` +
  3564. `L${w * 0.2},${h * 0.6} Z`
  3565. )
  3566. // 设置填充色
  3567. setBackground(element, cloud)
  3568. // 设置边框
  3569. if (element.borderWidth > 0) {
  3570. cloud.setAttribute("stroke", element.borderColor || "#000")
  3571. cloud.setAttribute("stroke-width", element.borderWidth || 1)
  3572. // 处理虚线边框
  3573. if (
  3574. element.borderType === "dotted" ||
  3575. element.borderType === "dashed"
  3576. ) {
  3577. if (element.borderStrokeDasharray) {
  3578. cloud.setAttribute(
  3579. "stroke-dasharray",
  3580. element.borderStrokeDasharray
  3581. )
  3582. } else if (element.borderType === "dotted") {
  3583. cloud.setAttribute("stroke-dasharray", "1, 3")
  3584. } else if (element.borderType === "dashed") {
  3585. cloud.setAttribute("stroke-dasharray", "5, 5")
  3586. }
  3587. }
  3588. }
  3589. svg.appendChild(cloud)
  3590. break
  3591. case "blockArc":
  3592. const blockArc = document.createElementNS(
  3593. "http://www.w3.org/2000/svg",
  3594. "path"
  3595. )
  3596. // 计算弧形参数
  3597. const rx = element.width / 2
  3598. const ry = element.height / 2
  3599. const innerRatio = 0.86 // 根据示例计算的内弧半径比例
  3600. const innerRx = rx * innerRatio
  3601. const innerRy = ry * innerRatio
  3602. // 构建路径
  3603. const path2 = `
  3604. M 0,${ry}
  3605. A ${rx} ${ry} 0 1 1 ${element.width} ${ry}
  3606. L ${element.width - (rx - innerRx)},${ry}
  3607. A ${innerRx} ${innerRy} 0 1 0 ${rx - innerRx},${ry}
  3608. Z`
  3609. blockArc.setAttribute("d", path2.trim())
  3610. // 设置填充色
  3611. setBackground(element, blockArc)
  3612. // 设置边框
  3613. if (element.borderWidth > 0) {
  3614. blockArc.setAttribute("stroke", element.borderColor || "#000")
  3615. blockArc.setAttribute("stroke-width", element.borderWidth || 1)
  3616. if (
  3617. element.borderType === "dotted" ||
  3618. element.borderType === "dashed"
  3619. ) {
  3620. if (element.borderStrokeDasharray) {
  3621. blockArc.setAttribute(
  3622. "stroke-dasharray",
  3623. element.borderStrokeDasharray
  3624. )
  3625. } else if (element.borderType === "dotted") {
  3626. blockArc.setAttribute("stroke-dasharray", "1, 3")
  3627. } else if (element.borderType === "dashed") {
  3628. blockArc.setAttribute("stroke-dasharray", "5, 5")
  3629. }
  3630. }
  3631. }
  3632. svg.appendChild(blockArc)
  3633. break
  3634. case "rect":
  3635. default:
  3636. const rect = document.createElementNS(
  3637. "http://www.w3.org/2000/svg",
  3638. "rect"
  3639. )
  3640. rect.setAttribute("x", 0)
  3641. rect.setAttribute("y", 0)
  3642. rect.setAttribute("width", element.width)
  3643. rect.setAttribute("height", element.height)
  3644. if (element.fill && element.fill.type) {
  3645. // 设置填充色
  3646. if (element.fill.type === "color") {
  3647. rect.setAttribute("fill", element.fill.value || "transparent")
  3648. } else if (element.fill.type === "gradient") {
  3649. // 渐变填充
  3650. const { colors, path, rot } = element.fill.value
  3651. if (colors && colors.length >= 2) {
  3652. const gradientType = path === "rect" ? "linear" : "radial"
  3653. const gradientAngle =
  3654. gradientType === "linear" ? (90 - (rot || 0)) % 360 : rot || 0
  3655. let gradientString = `${gradientType}-gradient(`
  3656. if (gradientType === "linear") {
  3657. gradientString += `${gradientAngle}deg, `
  3658. }
  3659. colors.forEach((color, i) => {
  3660. gradientString += `${color.color} ${color.pos}${
  3661. i < colors.length - 1 ? ", " : ""
  3662. }`
  3663. })
  3664. gradientString += ")"
  3665. // 创建渐变定义
  3666. const gradientDef = document.createElementNS(
  3667. "http://www.w3.org/2000/svg",
  3668. "defs"
  3669. )
  3670. const gradientEl = document.createElementNS(
  3671. "http://www.w3.org/2000/svg",
  3672. gradientType === "linear"
  3673. ? "linearGradient"
  3674. : "radialGradient"
  3675. )
  3676. const gradientId = `gradient-${Date.now()}-${Math.random()
  3677. .toString(36)
  3678. .substr(2, 9)}`
  3679. gradientEl.setAttribute("id", gradientId)
  3680. // 设置渐变属性
  3681. if (gradientType === "linear") {
  3682. gradientEl.setAttribute(
  3683. "gradientTransform",
  3684. `rotate(${gradientAngle})`
  3685. )
  3686. }
  3687. // 添加渐变色标
  3688. colors.forEach((color) => {
  3689. const stop = document.createElementNS(
  3690. "http://www.w3.org/2000/svg",
  3691. "stop"
  3692. )
  3693. stop.setAttribute("offset", color.pos)
  3694. stop.setAttribute("stop-color", color.color)
  3695. gradientEl.appendChild(stop)
  3696. })
  3697. gradientDef.appendChild(gradientEl)
  3698. svg.appendChild(gradientDef)
  3699. // 应用渐变
  3700. rect.setAttribute("fill", `url(#${gradientId})`)
  3701. }
  3702. } else if (element.fill.type === "image") {
  3703. // 创建图案填充
  3704. const pattern = document.createElementNS(
  3705. "http://www.w3.org/2000/svg",
  3706. "pattern"
  3707. )
  3708. const patternId = `pattern-${Date.now()}-${Math.random()
  3709. .toString(36)
  3710. .substr(2, 9)}`
  3711. pattern.setAttribute("id", patternId)
  3712. pattern.setAttribute("patternUnits", "userSpaceOnUse")
  3713. pattern.setAttribute("width", "100%")
  3714. pattern.setAttribute("height", "100%")
  3715. // 创建图片元素
  3716. const image = document.createElementNS(
  3717. "http://www.w3.org/2000/svg",
  3718. "image"
  3719. )
  3720. image.setAttribute("width", "100%")
  3721. image.setAttribute("height", "100%")
  3722. image.setAttribute("preserveAspectRatio", "xMidYMid slice")
  3723. image.setAttributeNS(
  3724. "http://www.w3.org/1999/xlink",
  3725. "href",
  3726. element.fill.value.picBase64
  3727. )
  3728. pattern.appendChild(image)
  3729. // 添加pattern到defs
  3730. const defs = document.createElementNS(
  3731. "http://www.w3.org/2000/svg",
  3732. "defs"
  3733. )
  3734. defs.appendChild(pattern)
  3735. svg.appendChild(defs)
  3736. // 应用图案填充
  3737. rect.setAttribute("fill", `url(#${patternId})`)
  3738. } else {
  3739. rect.setAttribute("fill", "transparent")
  3740. }
  3741. } else {
  3742. rect.setAttribute("fill", "#ffffff00")
  3743. }
  3744. // 设置边框
  3745. if (element.borderWidth > 0) {
  3746. rect.setAttribute("stroke", element.borderColor || "#000")
  3747. rect.setAttribute("stroke-width", element.borderWidth || 1)
  3748. // 处理虚线边框
  3749. if (
  3750. element.borderType === "dotted" ||
  3751. element.borderType === "dashed"
  3752. ) {
  3753. if (element.borderStrokeDasharray) {
  3754. rect.setAttribute(
  3755. "stroke-dasharray",
  3756. element.borderStrokeDasharray
  3757. )
  3758. } else if (element.borderType === "dotted") {
  3759. rect.setAttribute("stroke-dasharray", "1, 3")
  3760. } else if (element.borderType === "dashed") {
  3761. rect.setAttribute("stroke-dasharray", "5, 5")
  3762. }
  3763. }
  3764. }
  3765. svg.appendChild(rect)
  3766. break
  3767. }
  3768. const transformList = []
  3769. let rotateDeg = element.rotate || 0
  3770. if (element.isFlipV) {
  3771. transformList.push(`scaleY(-1)`)
  3772. rotateDeg = -rotateDeg // 垂直翻转时反转旋转方向
  3773. }
  3774. if (element.isFlipH) {
  3775. transformList.push(`scaleX(-1)`)
  3776. rotateDeg = -rotateDeg // 水平翻转时反转旋转方向
  3777. }
  3778. if (element.rotate) {
  3779. transformList.push(`rotate(${rotateDeg}deg)`)
  3780. }
  3781. if (transformList.length > 0) {
  3782. el.style.transform = transformList.join(" ")
  3783. el.style.transformOrigin = "center center"
  3784. }
  3785. el.appendChild(svg)
  3786. // 设置形状内容
  3787. if (element.content) {
  3788. const contentContainer = document.createElement("div")
  3789. contentContainer.innerHTML = this.convertPtToPxInContent(
  3790. element.content
  3791. )
  3792. contentContainer.style.position = "absolute"
  3793. contentContainer.style.width = element.width + "px"
  3794. contentContainer.style.height = element.height + "px"
  3795. contentContainer.style.top = "0px"
  3796. contentContainer.style.left = "0px"
  3797. contentContainer.style.display = "flex"
  3798. contentContainer.style.alignItems = "center"
  3799. contentContainer.style.justifyContent = "center"
  3800. contentContainer.style.zIndex = element.order
  3801. contentContainer.style.pointerEvents = "none"
  3802. const transformList = []
  3803. let rotateDeg = element.rotate || 0
  3804. if (element.isFlipV) {
  3805. transformList.push(`scaleY(-1)`)
  3806. rotateDeg = -rotateDeg // 垂直翻转时反转旋转方向
  3807. }
  3808. if (element.isFlipH) {
  3809. transformList.push(`scaleX(-1)`)
  3810. rotateDeg = -rotateDeg // 水平翻转时反转旋转方向
  3811. }
  3812. if (element.rotate) {
  3813. transformList.push(`rotate(${rotateDeg}deg)`)
  3814. }
  3815. if (transformList.length > 0) {
  3816. contentContainer.style.transform = transformList.join(" ")
  3817. contentContainer.style.transformOrigin = "center center"
  3818. }
  3819. el.appendChild(contentContainer)
  3820. }
  3821. return el
  3822. },
  3823. // 创建表格元素
  3824. createTableElement(element) {
  3825. const el = document.createElement("div")
  3826. el.style.position = "absolute"
  3827. el.style.top = element.top + "px"
  3828. el.style.left = element.left + "px"
  3829. el.style.width = element.width + "px"
  3830. el.style.height = element.height + "px"
  3831. el.style.zIndex = element.order
  3832. // 创建表格元素
  3833. const table = document.createElement("table")
  3834. table.style.width = element.width + "px"
  3835. table.style.height = element.height + "px"
  3836. table.style.borderCollapse = "collapse"
  3837. table.style.tableLayout = "fixed"
  3838. // 设置表格边框
  3839. if (element.borders) {
  3840. if (element.borders.all) {
  3841. const border = element.borders.all
  3842. table.style.border = `${border.borderWidth || 1}px ${
  3843. border.borderType || "solid"
  3844. } ${border.borderColor || "#000"}`
  3845. } else {
  3846. // 分别设置四边边框
  3847. if (element.borders.top) {
  3848. table.style.borderTop = `${
  3849. element.borders.top.borderWidth || 1
  3850. }px ${element.borders.top.borderType || "solid"} ${
  3851. element.borders.top.borderColor || "#000"
  3852. }`
  3853. }
  3854. if (element.borders.bottom) {
  3855. table.style.borderBottom = `${
  3856. element.borders.bottom.borderWidth || 1
  3857. }px ${element.borders.bottom.borderType || "solid"} ${
  3858. element.borders.bottom.borderColor || "#000"
  3859. }`
  3860. }
  3861. if (element.borders.left) {
  3862. table.style.borderLeft = `${
  3863. element.borders.left.borderWidth || 1
  3864. }px ${element.borders.left.borderType || "solid"} ${
  3865. element.borders.left.borderColor || "#000"
  3866. }`
  3867. }
  3868. if (element.borders.right) {
  3869. table.style.borderRight = `${
  3870. element.borders.right.borderWidth || 1
  3871. }px ${element.borders.right.borderType || "solid"} ${
  3872. element.borders.right.borderColor || "#000"
  3873. }`
  3874. }
  3875. }
  3876. }
  3877. // 创建表格内容
  3878. const tbody = document.createElement("tbody")
  3879. // 处理表格数据
  3880. if (element.data && element.data.length > 0) {
  3881. element.data.forEach((rowData, rowIndex) => {
  3882. const tr = document.createElement("tr")
  3883. rowData.forEach((cell, colIndex) => {
  3884. // 跳过被合并的单元格
  3885. if (cell.hMerge) return
  3886. const td = document.createElement("td")
  3887. // 设置单元格内容
  3888. if (cell.text) {
  3889. td.innerHTML = this.convertPtToPxInContent(cell.text)
  3890. }
  3891. // 设置单元格样式
  3892. td.style.padding = "0px"
  3893. td.style.verticalAlign = "middle"
  3894. // 设置文本样式
  3895. if (cell.fontColor) td.style.color = cell.fontColor
  3896. if (cell.fontSize) td.style.fontSize = cell.fontSize
  3897. if (cell.fontFamily) td.style.fontFamily = cell.fontFamily
  3898. if (cell.bold) td.style.fontWeight = "bold"
  3899. if (cell.italic) td.style.fontStyle = "italic"
  3900. if (cell.underline) td.style.textDecoration = "underline"
  3901. if (cell.align) td.style.textAlign = cell.align
  3902. // 设置背景色
  3903. if (cell.fillColor) td.style.backgroundColor = cell.fillColor
  3904. // 设置单元格边框
  3905. if (cell.borders) {
  3906. if (cell.borders.all) {
  3907. const border = cell.borders.all
  3908. td.style.border = `${border.borderWidth || 1}px ${
  3909. border.borderType || "solid"
  3910. } ${border.borderColor || "#000"}`
  3911. } else {
  3912. // 分别设置四边边框
  3913. if (cell.borders.top) {
  3914. td.style.borderTop = `${
  3915. cell.borders.top.borderWidth || 1
  3916. }px ${cell.borders.top.borderType || "solid"} ${
  3917. cell.borders.top.borderColor || "#000"
  3918. }`
  3919. }
  3920. if (cell.borders.bottom) {
  3921. td.style.borderBottom = `${
  3922. cell.borders.bottom.borderWidth || 1
  3923. }px ${cell.borders.bottom.borderType || "solid"} ${
  3924. cell.borders.bottom.borderColor || "#000"
  3925. }`
  3926. }
  3927. if (cell.borders.left) {
  3928. td.style.borderLeft = `${
  3929. cell.borders.left.borderWidth || 1
  3930. }px ${cell.borders.left.borderType || "solid"} ${
  3931. cell.borders.left.borderColor || "#000"
  3932. }`
  3933. }
  3934. if (cell.borders.right) {
  3935. td.style.borderRight = `${
  3936. cell.borders.right.borderWidth || 1
  3937. }px ${cell.borders.right.borderType || "solid"} ${
  3938. cell.borders.right.borderColor || "#000"
  3939. }`
  3940. }
  3941. }
  3942. }
  3943. td.style.width = element.colWidths[colIndex] + "px"
  3944. // 设置单元格合并
  3945. if (cell.colSpan && cell.colSpan > 1) {
  3946. td.colSpan = cell.colSpan
  3947. td.style.width = element.colWidths[colIndex] * cell.colSpan + "px"
  3948. }
  3949. if (cell.rowSpan && cell.rowSpan > 1) {
  3950. td.rowSpan = cell.rowSpan
  3951. }
  3952. tr.appendChild(td)
  3953. })
  3954. tr.style.height = element.rowHeights[rowIndex] + "px"
  3955. tbody.appendChild(tr)
  3956. })
  3957. }
  3958. table.appendChild(tbody)
  3959. el.appendChild(table)
  3960. return el
  3961. },
  3962. // 创建图表元素
  3963. createChartElement(element) {
  3964. // 1. 创建基础容器
  3965. const el = document.createElement("div")
  3966. el.style.position = "absolute"
  3967. el.style.top = element.top + "px"
  3968. el.style.left = element.left + "px"
  3969. el.style.width = element.width + "px"
  3970. el.style.height = element.height + "px"
  3971. el.style.zIndex = element.order
  3972. // 2. 创建SVG画布
  3973. const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
  3974. svg.setAttribute("width", element.width)
  3975. svg.setAttribute("height", element.height)
  3976. svg.setAttribute("viewBox", `0 0 ${element.width} ${element.height}`)
  3977. // 3. 设置图表内边距
  3978. const padding = {
  3979. top: 60, // 为图例留出空间
  3980. right: 40, // 右侧边距
  3981. bottom: 60, // X轴标签空间
  3982. left: 60, // Y轴标签空间
  3983. }
  3984. // 4. 计算实际绘图区域
  3985. const chartWidth = element.width - padding.left - padding.right
  3986. const chartHeight = element.height - padding.top - padding.bottom
  3987. // 处理不同图表类型
  3988. switch (element.chartType) {
  3989. case "barChart":
  3990. // 绘制柱状图
  3991. this.drawBarChart(svg, element, {
  3992. padding,
  3993. chartWidth,
  3994. chartHeight,
  3995. barDir: element.barDir || "col",
  3996. grouping: element.grouping || "clustered",
  3997. })
  3998. break
  3999. case "pieChart":
  4000. case "doughnutChart":
  4001. this.drawDonutChart(svg, element, chartWidth, chartHeight)
  4002. break
  4003. default:
  4004. // 占位符
  4005. svg.innerHTML = `<text x="${element.width / 2}" y="${
  4006. element.height / 2
  4007. }" text-anchor="middle" fill="#999" font-size="12px">
  4008. 暂不支持该类型图表
  4009. </text>`
  4010. console.warn("Unsupported chart type:", element.chartType)
  4011. }
  4012. el.appendChild(svg)
  4013. return el
  4014. },
  4015. drawDonutChart(svg, element, chartWidth, chartHeight) {
  4016. // 数据验证
  4017. if (!element?.data?.[0]?.values) return
  4018. const series = element.data[0]
  4019. const values = series.values.map((v) => Number(v.y) || 0)
  4020. const total = values.reduce((sum, v) => sum + v, 0)
  4021. if (total === 0) return
  4022. // 基础配置
  4023. const cx = chartWidth / 2
  4024. const cy = chartHeight / 2
  4025. // 保持较大的外半径
  4026. const outerR = (Math.min(chartWidth, chartHeight) / 2) * 0.98
  4027. // 处理空心大小
  4028. const holeSize = element.holeSize ? parseInt(element.holeSize) : 50
  4029. const innerR = outerR * (holeSize / 100)
  4030. // 默认颜色和自定义颜色处理
  4031. const defaultColors = [
  4032. "#4e79a7",
  4033. "#f28e2b",
  4034. "#e15759",
  4035. "#76b7b2",
  4036. "#59a14f",
  4037. "#edc949",
  4038. "#af7aa1",
  4039. "#ff9da7",
  4040. ]
  4041. const colors =
  4042. element.colors?.map(
  4043. (color, i) => color || defaultColors[i % defaultColors.length]
  4044. ) || defaultColors
  4045. // 标签数据
  4046. const labels = series.xlabels || {}
  4047. // 创建图表组
  4048. const chartGroup = document.createElementNS(
  4049. "http://www.w3.org/2000/svg",
  4050. "g"
  4051. )
  4052. chartGroup.setAttribute("transform", `translate(${cx},${cy})`)
  4053. // 绘制扇形
  4054. let startAngle = -Math.PI / 2 // 从顶部开始绘制
  4055. values.forEach((value, index) => {
  4056. if (value <= 0) return
  4057. const percentage = value / total
  4058. const angle = percentage * Math.PI * 2
  4059. const endAngle = startAngle + angle
  4060. // 计算路径点 (相对于组中心 0,0)
  4061. const x1 = outerR * Math.cos(startAngle)
  4062. const y1 = outerR * Math.sin(startAngle)
  4063. const x2 = outerR * Math.cos(endAngle)
  4064. const y2 = outerR * Math.sin(endAngle)
  4065. const x3 = innerR * Math.cos(endAngle)
  4066. const y3 = innerR * Math.sin(endAngle)
  4067. const x4 = innerR * Math.cos(startAngle)
  4068. const y4 = innerR * Math.sin(startAngle)
  4069. // 构建路径
  4070. const path = document.createElementNS(
  4071. "http://www.w3.org/2000/svg",
  4072. "path"
  4073. )
  4074. const largeArc = angle > Math.PI ? 1 : 0
  4075. const d = [
  4076. `M ${x1} ${y1}`,
  4077. `A ${outerR} ${outerR} 0 ${largeArc} 1 ${x2} ${y2}`,
  4078. `L ${x3} ${y3}`,
  4079. `A ${innerR} ${innerR} 0 ${largeArc} 0 ${x4} ${y4}`,
  4080. "Z",
  4081. ].join(" ")
  4082. path.setAttribute("d", d)
  4083. path.setAttribute("fill", colors[index % colors.length]) // 确保颜色循环使用
  4084. // 添加交互效果
  4085. path.style.transition = "transform 0.2s"
  4086. path.addEventListener("mouseover", () => {
  4087. path.style.transform = "scale(1.03)"
  4088. })
  4089. path.addEventListener("mouseout", () => {
  4090. path.style.transform = "scale(1)"
  4091. })
  4092. chartGroup.appendChild(path)
  4093. // 添加标签
  4094. const midAngle = startAngle + angle / 2
  4095. const labelR = outerR * 1.1
  4096. const labelX = labelR * Math.cos(midAngle)
  4097. const labelY = labelR * Math.sin(midAngle)
  4098. const text = document.createElementNS(
  4099. "http://www.w3.org/2000/svg",
  4100. "text"
  4101. )
  4102. text.setAttribute("x", labelX)
  4103. text.setAttribute("y", labelY)
  4104. text.setAttribute("text-anchor", labelX < 0 ? "end" : "start")
  4105. text.setAttribute("dominant-baseline", "middle")
  4106. text.setAttribute("fill", "#555")
  4107. text.setAttribute("font-size", "9")
  4108. text.setAttribute("font-weight", "normal")
  4109. const tspanLabel = document.createElementNS(
  4110. "http://www.w3.org/2000/svg",
  4111. "tspan"
  4112. )
  4113. tspanLabel.setAttribute("x", labelX)
  4114. tspanLabel.textContent = labels[index] || `类别 ${index + 1}`
  4115. text.appendChild(tspanLabel)
  4116. const tspanPercent = document.createElementNS(
  4117. "http://www.w3.org/2000/svg",
  4118. "tspan"
  4119. )
  4120. tspanPercent.setAttribute("x", labelX)
  4121. tspanPercent.setAttribute("dy", "1.2em")
  4122. tspanPercent.textContent = `${(percentage * 100).toFixed(1)}%`
  4123. text.appendChild(tspanPercent)
  4124. chartGroup.appendChild(text)
  4125. startAngle = endAngle
  4126. })
  4127. svg.appendChild(chartGroup)
  4128. const padding = 50
  4129. svg.setAttribute(
  4130. "viewBox",
  4131. `${-cx / 2} ${-cy / 2} ${chartWidth + padding * 2} ${
  4132. chartHeight + padding * 2
  4133. }`
  4134. )
  4135. svg.style.overflow = "visible"
  4136. },
  4137. // 绘制柱状图
  4138. drawBarChart(svg, element, options) {
  4139. const { padding, chartWidth, chartHeight, barDir, grouping } = options
  4140. const series = element.data
  4141. const categories = series[0].xlabels
  4142. const categoryCount = Object.keys(categories).length
  4143. // 1. 计算最大值
  4144. let maxValue = 0
  4145. series.forEach((serie) => {
  4146. const seriesMax = Math.max(...serie.values.map((v) => v.y))
  4147. maxValue = Math.max(maxValue, seriesMax)
  4148. })
  4149. maxValue = maxValue * 1.2 // 增加20%空间
  4150. // 2. 计算柱子布局
  4151. const groupWidth = chartWidth / categoryCount
  4152. const barWidth =
  4153. grouping === "clustered"
  4154. ? (groupWidth * 0.6) / series.length // 分组模式
  4155. : groupWidth * 0.6 // 堆叠模式
  4156. const barSpacing =
  4157. (groupWidth * 0.4) / (grouping === "clustered" ? series.length + 1 : 2)
  4158. // 3. 绘制坐标轴
  4159. // X轴
  4160. const xAxisPath = document.createElementNS(
  4161. "http://www.w3.org/2000/svg",
  4162. "path"
  4163. )
  4164. xAxisPath.setAttribute(
  4165. "d",
  4166. `M${padding.left},${element.height - padding.bottom} L${
  4167. element.width - padding.right
  4168. },${element.height - padding.bottom}`
  4169. )
  4170. xAxisPath.setAttribute("stroke", "#000")
  4171. xAxisPath.setAttribute("stroke-width", "1")
  4172. svg.appendChild(xAxisPath)
  4173. // Y轴
  4174. const yAxisPath = document.createElementNS(
  4175. "http://www.w3.org/2000/svg",
  4176. "path"
  4177. )
  4178. yAxisPath.setAttribute(
  4179. "d",
  4180. `M${padding.left},${padding.top} L${padding.left},${
  4181. element.height - padding.bottom
  4182. }`
  4183. )
  4184. yAxisPath.setAttribute("stroke", "#000")
  4185. yAxisPath.setAttribute("stroke-width", "1")
  4186. svg.appendChild(yAxisPath)
  4187. // 4. 绘制Y轴刻度和网格线
  4188. const yTickCount = 5
  4189. for (let i = 0; i <= yTickCount; i++) {
  4190. const y = padding.top + (chartHeight * i) / yTickCount
  4191. const value = maxValue - (maxValue * i) / yTickCount
  4192. // 水平网格线
  4193. const gridLine = document.createElementNS(
  4194. "http://www.w3.org/2000/svg",
  4195. "line"
  4196. )
  4197. gridLine.setAttribute("x1", padding.left)
  4198. gridLine.setAttribute("y1", y)
  4199. gridLine.setAttribute("x2", padding.left + chartWidth)
  4200. gridLine.setAttribute("y2", y)
  4201. gridLine.setAttribute("stroke", "#eee")
  4202. gridLine.setAttribute("stroke-width", "1")
  4203. svg.appendChild(gridLine)
  4204. // 刻度线
  4205. const tick = document.createElementNS(
  4206. "http://www.w3.org/2000/svg",
  4207. "line"
  4208. )
  4209. tick.setAttribute("x1", padding.left - 6)
  4210. tick.setAttribute("y1", y)
  4211. tick.setAttribute("x2", padding.left)
  4212. tick.setAttribute("y2", y)
  4213. tick.setAttribute("stroke", "#000")
  4214. tick.setAttribute("stroke-width", "1")
  4215. svg.appendChild(tick)
  4216. // 刻度值
  4217. const label = document.createElementNS(
  4218. "http://www.w3.org/2000/svg",
  4219. "text"
  4220. )
  4221. label.setAttribute("x", padding.left - 10)
  4222. label.setAttribute("y", y + 4)
  4223. label.setAttribute("text-anchor", "end")
  4224. label.setAttribute("font-size", "12px")
  4225. label.textContent = value.toFixed(1)
  4226. svg.appendChild(label)
  4227. }
  4228. // 5. 绘制数据条
  4229. series.forEach((serie, serieIndex) => {
  4230. serie.values.forEach((value, index) => {
  4231. const barHeight = (value.y / maxValue) * chartHeight
  4232. const x =
  4233. padding.left +
  4234. groupWidth * index +
  4235. (grouping === "clustered"
  4236. ? barSpacing * (serieIndex + 1) + barWidth * serieIndex
  4237. : barSpacing)
  4238. const y = element.height - padding.bottom - barHeight
  4239. // 绘制柱子
  4240. const bar = document.createElementNS(
  4241. "http://www.w3.org/2000/svg",
  4242. "rect"
  4243. )
  4244. bar.setAttribute("x", x)
  4245. bar.setAttribute("y", y)
  4246. bar.setAttribute("width", barWidth)
  4247. bar.setAttribute("height", barHeight)
  4248. bar.setAttribute(
  4249. "fill",
  4250. element.colors[serieIndex] || `hsl(${serieIndex * 60}, 70%, 50%)`
  4251. )
  4252. svg.appendChild(bar)
  4253. // 数值标签
  4254. if (element.marker) {
  4255. const label = document.createElementNS(
  4256. "http://www.w3.org/2000/svg",
  4257. "text"
  4258. )
  4259. label.setAttribute("x", x + barWidth / 2)
  4260. label.setAttribute("y", y - 5)
  4261. label.setAttribute("text-anchor", "middle")
  4262. label.setAttribute("font-size", "12px")
  4263. label.textContent = value.y.toFixed(1)
  4264. svg.appendChild(label)
  4265. }
  4266. })
  4267. })
  4268. // 6. 绘制X轴类别标签
  4269. Object.values(categories).forEach((label, index) => {
  4270. const x = padding.left + groupWidth * (index + 0.5)
  4271. const text = document.createElementNS(
  4272. "http://www.w3.org/2000/svg",
  4273. "text"
  4274. )
  4275. text.setAttribute("x", x)
  4276. text.setAttribute("y", element.height - padding.bottom + 20)
  4277. text.setAttribute("text-anchor", "middle")
  4278. text.setAttribute("font-size", "12px")
  4279. text.textContent = label
  4280. svg.appendChild(text)
  4281. })
  4282. // 7. 绘制图例
  4283. series.forEach((serie, index) => {
  4284. const legendX = padding.left + index * 120
  4285. const legendY = 20
  4286. const rect = document.createElementNS(
  4287. "http://www.w3.org/2000/svg",
  4288. "rect"
  4289. )
  4290. rect.setAttribute("x", legendX)
  4291. rect.setAttribute("y", legendY)
  4292. rect.setAttribute("width", 15)
  4293. rect.setAttribute("height", 15)
  4294. rect.setAttribute(
  4295. "fill",
  4296. element.colors[index] || `hsl(${index * 60}, 70%, 50%)`
  4297. )
  4298. svg.appendChild(rect)
  4299. const text = document.createElementNS(
  4300. "http://www.w3.org/2000/svg",
  4301. "text"
  4302. )
  4303. text.setAttribute("x", legendX + 25)
  4304. text.setAttribute("y", legendY + 12)
  4305. text.setAttribute("font-size", "12px")
  4306. text.textContent = serie.key
  4307. svg.appendChild(text)
  4308. })
  4309. },
  4310. // 绘制网格和刻度
  4311. drawGrid(svg, padding, width, height, maxValue) {
  4312. const yTickCount = 5
  4313. for (let i = 0; i <= yTickCount; i++) {
  4314. const y = padding.top + (height * i) / yTickCount
  4315. const value = maxValue - (maxValue * i) / yTickCount
  4316. // 刻度线
  4317. const tick = document.createElementNS(
  4318. "http://www.w3.org/2000/svg",
  4319. "line"
  4320. )
  4321. tick.setAttribute("x1", padding.left - 5)
  4322. tick.setAttribute("x2", padding.left)
  4323. tick.setAttribute("y1", y)
  4324. tick.setAttribute("y2", y)
  4325. tick.setAttribute("stroke", "#000")
  4326. svg.appendChild(tick)
  4327. // 刻度值
  4328. const label = document.createElementNS(
  4329. "http://www.w3.org/2000/svg",
  4330. "text"
  4331. )
  4332. label.setAttribute("x", padding.left - 8)
  4333. label.setAttribute("y", y + 4)
  4334. label.setAttribute("text-anchor", "end")
  4335. label.setAttribute("font-size", "12px")
  4336. label.textContent = value.toFixed(1)
  4337. svg.appendChild(label)
  4338. }
  4339. },
  4340. // 绘制类别标签
  4341. drawCategoryLabels(svg, categories, padding, groupWidth, barDir) {
  4342. Object.values(categories).forEach((label, index) => {
  4343. const text = document.createElementNS(
  4344. "http://www.w3.org/2000/svg",
  4345. "text"
  4346. )
  4347. if (barDir === "col") {
  4348. text.setAttribute("x", padding.left + groupWidth * (index + 0.5))
  4349. text.setAttribute("y", svg.height.baseVal.value - padding.bottom + 20)
  4350. text.setAttribute("text-anchor", "middle")
  4351. } else {
  4352. text.setAttribute("x", padding.left - 10)
  4353. text.setAttribute("y", padding.top + groupWidth * (index + 0.5))
  4354. text.setAttribute("text-anchor", "end")
  4355. text.setAttribute("dominant-baseline", "middle")
  4356. }
  4357. text.setAttribute("font-size", "12px")
  4358. text.textContent = label
  4359. svg.appendChild(text)
  4360. })
  4361. },
  4362. // 绘制图例
  4363. drawLegend(svg, series, colors, padding) {
  4364. series.forEach((serie, index) => {
  4365. const legendX = padding.left + index * 100
  4366. const legendY = 20
  4367. const rect = document.createElementNS(
  4368. "http://www.w3.org/2000/svg",
  4369. "rect"
  4370. )
  4371. rect.setAttribute("x", legendX)
  4372. rect.setAttribute("y", legendY)
  4373. rect.setAttribute("width", 15)
  4374. rect.setAttribute("height", 15)
  4375. rect.setAttribute(
  4376. "fill",
  4377. colors[index] || `hsl(${index * 60}, 70%, 50%)`
  4378. )
  4379. svg.appendChild(rect)
  4380. const text = document.createElementNS(
  4381. "http://www.w3.org/2000/svg",
  4382. "text"
  4383. )
  4384. text.setAttribute("x", legendX + 20)
  4385. text.setAttribute("y", legendY + 12)
  4386. text.setAttribute("font-size", "12px")
  4387. text.textContent = serie.key
  4388. svg.appendChild(text)
  4389. })
  4390. },
  4391. // 创建SmartArt图表元素
  4392. createDiagramElement(element) {
  4393. const el = document.createElement("div")
  4394. el.style.position = "absolute"
  4395. el.style.top = element.top + "px"
  4396. el.style.left = element.left + "px"
  4397. el.style.width = element.width + "px"
  4398. el.style.height = element.height + "px"
  4399. el.style.zIndex = element.order
  4400. // 递归渲染SmartArt节点
  4401. const renderDiagramNode = (node) => {
  4402. const nodeEl = document.createElement("div")
  4403. nodeEl.style.position = "absolute"
  4404. nodeEl.style.left = node.left + "px"
  4405. nodeEl.style.top = node.top + "px"
  4406. nodeEl.style.width = node.width + "px"
  4407. nodeEl.style.height = node.height + "px"
  4408. // 设置边框
  4409. if (node.borderWidth > 0) {
  4410. nodeEl.style.border = `${node.borderWidth}px ${node.borderType} ${node.borderColor}`
  4411. if (
  4412. node.borderStrokeDasharray &&
  4413. node.borderStrokeDasharray !== "0"
  4414. ) {
  4415. nodeEl.style.borderStyle = "dashed"
  4416. }
  4417. }
  4418. // 设置背景填充
  4419. if (node.fill && node.fill.type === "color") {
  4420. nodeEl.style.backgroundColor = node.fill.value
  4421. }
  4422. // 设置内容
  4423. if (node.content) {
  4424. nodeEl.innerHTML = this.convertPtToPxInContent(node.content)
  4425. }
  4426. // 设置垂直对齐
  4427. if (node.vAlign === "mid") {
  4428. nodeEl.style.display = "flex"
  4429. nodeEl.style.alignItems = "center"
  4430. nodeEl.style.justifyContent = "center"
  4431. }
  4432. // 设置翻转
  4433. const transforms = []
  4434. if (node.isFlipV) {
  4435. transforms.push("scaleY(-1)")
  4436. }
  4437. if (node.isFlipH) {
  4438. transforms.push("scaleX(-1)")
  4439. }
  4440. if (transforms.length > 0) {
  4441. nodeEl.style.transform = transforms.join(" ")
  4442. }
  4443. return nodeEl
  4444. }
  4445. // 按照 order 排序元素
  4446. const sortedElements = [...element.elements].sort(
  4447. (a, b) => a.order - b.order
  4448. )
  4449. // 渲染所有节点
  4450. sortedElements.forEach((node) => {
  4451. const nodeEl = renderDiagramNode(node)
  4452. el.appendChild(nodeEl)
  4453. })
  4454. return el
  4455. },
  4456. // 创建数学公式元素
  4457. createMathElement(element) {
  4458. const el = document.createElement("div")
  4459. el.style.position = "absolute"
  4460. el.style.top = element.top + "px"
  4461. el.style.left = element.left + "px"
  4462. el.style.width = element.width + "px"
  4463. el.style.height = element.height + "px"
  4464. // 如果有公式图片,优先使用图片显示
  4465. if (element.picBase64) {
  4466. const img = document.createElement("img")
  4467. img.src = element.picBase64
  4468. img.style.width = "100%"
  4469. img.style.height = "100%"
  4470. img.style.objectFit = "contain"
  4471. el.appendChild(img)
  4472. return el
  4473. }
  4474. // 如果有 LaTeX 表达式,使用 MathJax 渲染
  4475. if (element.latex) {
  4476. // 创建公式容器
  4477. const mathContainer = document.createElement("div")
  4478. mathContainer.style.width = "100%"
  4479. mathContainer.style.height = "100%"
  4480. mathContainer.style.display = "flex"
  4481. mathContainer.style.alignItems = "center"
  4482. mathContainer.style.justifyContent = "center"
  4483. // 添加 LaTeX 公式
  4484. mathContainer.innerHTML = `\\[${element.latex}\\]`
  4485. // 如果 MathJax 不可用,显示原始 LaTeX
  4486. mathContainer.style.fontFamily = "monospace"
  4487. mathContainer.style.whiteSpace = "pre-wrap"
  4488. mathContainer.style.padding = "10px"
  4489. mathContainer.textContent = element.latex
  4490. el.appendChild(mathContainer)
  4491. }
  4492. return el
  4493. },
  4494. // 创建文本元素
  4495. createTextElement(element) {
  4496. const el = document.createElement("div")
  4497. if (element.content) {
  4498. // 转换内容中的pt单位为px单位
  4499. const convertedContent = this.convertPtToPxInContent(element.content)
  4500. el.innerHTML = convertedContent
  4501. // 设置文本样式
  4502. el.style.width = element.width + "px"
  4503. el.style.height = element.height + "px"
  4504. el.style.color = element.fontColor || "#000"
  4505. el.style.fontSize = element.fontSize
  4506. el.style.fontFamily = element.fontFamily || "Arial"
  4507. el.style.textAlign = element.align || "left"
  4508. el.style.fontWeight = element.bold ? "bold" : "normal"
  4509. el.style.fontStyle = element.italic ? "italic" : "normal"
  4510. el.style.textDecoration = element.underline ? "underline" : "none"
  4511. el.style.position = "absolute"
  4512. el.style.top = element.top + "px" || "0"
  4513. el.style.left = element.left + "px" || "0"
  4514. el.style.zIndex = element.order
  4515. el.style.whiteSpace = "pre-wrap"
  4516. // 添加垂直对齐支持
  4517. el.style.display = "flex"
  4518. el.style.flexDirection = "column"
  4519. switch (element.vAlign) {
  4520. case "up":
  4521. el.style.justifyContent = "flex-start"
  4522. break
  4523. case "mid":
  4524. el.style.justifyContent = "center"
  4525. break
  4526. case "down":
  4527. el.style.justifyContent = "flex-end"
  4528. break
  4529. default:
  4530. el.style.justifyContent = "flex-start"
  4531. }
  4532. // 设置段落间距
  4533. el.style.lineHeight = element.lineHeight + "px" || "1.2"
  4534. el.style.letterSpacing = element.charSpacing
  4535. ? `${element.charSpacing}px`
  4536. : "normal"
  4537. }
  4538. return el
  4539. },
  4540. // 调整颜色明暗度
  4541. adjustBrightness(color, factor) {
  4542. if (color === "transparent") return color
  4543. const hex = color.replace("#", "")
  4544. const r = Math.min(
  4545. 255,
  4546. Math.round(parseInt(hex.substr(0, 2), 16) * factor)
  4547. )
  4548. const g = Math.min(
  4549. 255,
  4550. Math.round(parseInt(hex.substr(2, 2), 16) * factor)
  4551. )
  4552. const b = Math.min(
  4553. 255,
  4554. Math.round(parseInt(hex.substr(4, 2), 16) * factor)
  4555. )
  4556. return `#${r.toString(16).padStart(2, "0")}${g
  4557. .toString(16)
  4558. .padStart(2, "0")}${b.toString(16).padStart(2, "0")}`
  4559. },
  4560. convertPtToPxInContent(content) {
  4561. if (!content) return content
  4562. // 使用正则表达式查找并替换
  4563. return content.replace(/(\d+\.?\d*)(pt|PT)/g, (match, size) => {
  4564. // 将 pt 转换为 px(1pt ≈ 1.33333px)
  4565. const pxSize = size
  4566. return `${pxSize}px`
  4567. })
  4568. },
  4569. processElements(elements, slideIndex) {
  4570. if (!elements || !Array.isArray(elements)) return
  4571. // 使用 Map 存储原始顺序,避免多次排序
  4572. const orderMap = new Map(
  4573. elements.map((el, index) => [el, el.order || index])
  4574. )
  4575. // 一次性排序
  4576. elements.sort((a, b) => orderMap.get(a) - orderMap.get(b))
  4577. const processElement = (element, baseOrder) => {
  4578. // 设置当前元素的 order
  4579. element.order = baseOrder
  4580. // 如果有子元素,递归处理
  4581. if (element.elements?.length > 0) {
  4582. element.elements
  4583. .sort((a, b) => (a.order || 0) - (b.order || 0))
  4584. .forEach((child, idx) => {
  4585. processElement(child, baseOrder * 10 + idx + 1)
  4586. })
  4587. }
  4588. }
  4589. // 处理每个顶层元素
  4590. elements.forEach((element, index) => {
  4591. processElement(element, (slideIndex + 1) * 10 + index + 1)
  4592. })
  4593. },
  4594. },
  4595. }
  4596. </script>
  4597. <style scoped lang="less">
  4598. .pptx-container {
  4599. width: 100%;
  4600. height: 100%;
  4601. z-index: 99;
  4602. }
  4603. </style>