From 1746c4b0edbe9d26a290e896b9f9ee7d98244d1d Mon Sep 17 00:00:00 2001 From: MiniPear Date: Mon, 15 May 2023 10:07:40 +0800 Subject: [PATCH] fix(animation): non animation replace node (close: #5006) --- ...-chart-render-update-non-animation.spec.ts | 26 +++++++++ .../step0.png | Bin 0 -> 9675 bytes .../api/chart-render-update-non-animation.ts | 53 ++++++++++++++++++ __tests__/plots/api/index.ts | 1 + src/runtime/plot.ts | 5 +- 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 __tests__/integration/api-chart-render-update-non-animation.spec.ts create mode 100644 __tests__/integration/snapshots/api/chart-render-update-non-animation/step0.png create mode 100644 __tests__/plots/api/chart-render-update-non-animation.ts diff --git a/__tests__/integration/api-chart-render-update-non-animation.spec.ts b/__tests__/integration/api-chart-render-update-non-animation.spec.ts new file mode 100644 index 0000000000..4c0489701e --- /dev/null +++ b/__tests__/integration/api-chart-render-update-non-animation.spec.ts @@ -0,0 +1,26 @@ +import { chartRenderUpdateNonAnimation as render } from '../plots/api/chart-render-update-non-animation'; +import { createNodeGCanvas } from './utils/createNodeGCanvas'; +import { kebabCase } from './utils/kebabCase'; +import './utils/useCustomFetch'; +import './utils/useSnapshotMatchers'; + +describe('chart.options.autoFit', () => { + const dir = `${__dirname}/snapshots/api/${kebabCase(render.name)}`; + const canvas = createNodeGCanvas(800, 500); + + it('chart({ autoFit: true }) should fit parent container', async () => { + const { finished, chart, refreshed, button, ...rest } = render({ + canvas, + container: document.createElement('div'), + }); + await finished; + + button.dispatchEvent(new CustomEvent('click')); + await refreshed; + await expect(canvas).toMatchCanvasSnapshot(dir, 'step0'); + }); + + afterAll(() => { + canvas?.destroy(); + }); +}); diff --git a/__tests__/integration/snapshots/api/chart-render-update-non-animation/step0.png b/__tests__/integration/snapshots/api/chart-render-update-non-animation/step0.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0d4c16671ba09a3c30251de74d8990bd4376c2 GIT binary patch literal 9675 zcmbt)2~-p3`u+e_>$OTNtyCh?dr@hx3PofQgxIA1m006A@_d9R|0L=3Mz-;90mB<;_XG1TMKP!(1_#Ob3mVa)D zs*3>NBf$T_XQ3I_)Wexgcd+VU!Hz{#^!@(+fxtj&3k9pe!mlk{md`!d;3hs_|)k>BQXq( zADEizI_xDJ&+(BRm9eE$^w&i$FeuQwm540ov_;YmO-^|{MW;>sn zn@K9#X?dL;kv2TqmxSj(r-2_>O5Lh8j>pX3A z8J%#eB`m!z7bkF!pY^`HH5$;`^wgmUzYKPgX>;xF-pL04k9s`g1r!w#c)y@d{3%vf2dQET4XG5(+2iIw^u~O> z<4AR=j_nhb#L8{<%y{BPWnIS%=dz}Lfoq^x8|4>sSK^f`etZjP-L*l3Z?$CRa`i82 zb0qNBhdvLtugT8RJl|TFov4w*BF@}J#)0mVbPJ&NyMvv84_i<_C=paOmj}WKCI-w3Nhb9 z@?T`0a*0ZDfMRFdVYKdkE>E9DN!DD1A?SgCrg;bt9x`9h z!0t>Ce8jYNUH{mENyU&O4+jE3?F|BZv!_r(&}2jYoH-e`S~kV5%dOFiaf{W=*p4Z? z!^T|7*wu9#fRWzB&a?W(aLw}pV*#kS_xK3!OeTH>yA3BJ!e;fTx@186 z6b3m4UktUvd&-JY_Sv67{Et41k)Qa?m{_}+U`xPbM7Q-rk%mW10|pyPC(y=MA`xF7 zov`5-Ss{kXG}Q>|^*_S(I5{7y#ESU(cnz9qLE47`fb9A{Y+KjWrC7@JfKgey`O`k_ z3-~?v8*7n_tS5bD+*>UWc-|7EQ4Uk0h^H3%VNRO-I@Xq7;RXPhpKh&RPT8sfk99LG z@c~@A%Ht6@$`jr5JnfzoVB2sf=SgS5hd{I@2&?k9z6y|Z-MFe)OktfVeJayUHZ|Sn zr)Mb+%8&RWc}@Im)*Pt4w-cPblkW!<)<$)QuT&ht_jy<> zD}{L;WCtQny@TwuH|Et62e%|~b_dQAvv*t9oQyLD|a&8&^H0HRmyfIahku_3I2 z8b`JwN<{AEi9JOrm>G8_n%s8LP8e_TN9+41&PBV{;iCyC&H639jQA++dC!25STPIBq zoZG2CMH=)2GA<;5%LmewV3w{{T@Fv;Yyn{ViD4vpC1X>{yGU{|af>o$3BviLqqIhS zAmy;CzcpZVbM`69!ar-m7XYYb=hip07`&i89DNT$nRKk}m&Rm@3|_<0PK@eHPaBJT zdD*R3=Grz`?E+evgDo~8g8OgHlu8?N?e0f~+}ixY5oeJ-aY&m=e!WM;)tlh_6dQZ(!05KX@{rW7$=e=>>Io&7)e9Q z8>K_>_)_^+cK{&WIvBY!hN!s!^$ARK>I+QwP~|fZ`voh;M)7`-K#JTxQ@|*Dlm@Dp zvM`AxuM`0KFCN^Imw@7A1>ofc`95|EKP`)N4QM<`5}pH#Z2HXKOq#zi1EQ@rQ2rXX z;pIiAs?EHVRLyL~JwqkEciy4h)^atF%<%(s@5*wJVjYGh>+4Q=-|Wp1^M+H7kQHK~^w-5}QPX!Xz?4+76sH( zF9TD5y{EBAm^c{got=6T!pW{jHuIu(*V%=u`++=B{#(hG&Sk-cr7U^IY|ilMVQIcY z&-ifCxj~gf zA4Pi_@8Di(`lUQ6K}_WmEdZ@!m$~BHo0;jrkp8UU(W?0F)j?ilwP3A8SB-YrL*}Z? z|3pgk-(HS(Jv<9Nfm|U2NbTgJ>$6@?npQFSGVi6^;BQP7QOUo7pb{<}T%nnNd}vN5 zh0h{d1It{x2BGWpJ#Z0Jh_UV(3;_{Z&$Lf@bMerNrci9K*UTt#ptTs5|q~$@UDGGMt#-(n*RFA9CpKc zSD+OhD@(MYqe{g6H~=7|}?wB$2VhY|m_r!b5&9ehGehQjd=FUj)}& zLIKgPw4)ArA@`>g9_Od$n)RnBPp%|YGrlGtwZH6jGbPmzN`bPGFn3vV$qE?3kl%|n z3t^7AIZmg>+28cKImo{}qK@!pHU#DbYR)k>{t$rT&s%tigQi z_pJdSpcWB41eVWUtSO!-B@2B+u~@qbFhU-_D|foKrAB{(BKxOsy$YDVvR_>*2+{m3 z{Wh9$QsEm$Z+z)&aF2P*sS-3~QGWWJ`6f2>_x%+*%CurC@0&!&2*wi{0gJwOq-C+_ zU@z~@6Z>kUX8js-@Gn4pZ2vzQZyhAVlG#y5lgc0^3sGD>oH^~u=k}oTdJ;9xE5_2Y z#u0aK>8`{1L|hC~dr5f|=sD!1juG-ZNnZ1>VHv2~QG;gdpEb`}#mW}%;TEkJuU<&v zB3F+3KxD@r$=8-Z^k==U1wsQCw`gLxWXR$p!Rdb3fNF2{;)GDD;Tk-8Ae)ZRIDRo7 zwg$bru1^q9{`LUC|88lZ>AU%sBG69$BXJwU%ClJE=EzZ>A4pR8Fz(FvSG?;40Pfx0 zM1WmaFs_dsRq&R|A9Pk=u*0om5mWox62LU_h{_CTDl3k9TYpKq8pW?ENQjh7UuLY? zYbbX^D5~{D83N^n-CbSAV;b2`dW_?8xYSoygs#F$S}N4()QukkfY?9Krp;_Kzd|j3 z))e^;B0_4;*~D6~3F>_a7u4Q$IJ4=PF;MletIyTZYF;aKr|!_%iU1&|C_7klC%xm1 zZB!+$k{ACTLIZ~rioXwGD!L1%6`~UupYh^%{sQD(S@hLdXCjk!nvT2ko#fWb;)xr&Ql)6 zAFlj4e4F^!e-E1zsj*-LNcK{DO?8Zbhmpzc=Mjy#^Z7|e{yw`SB5}%|((K(=5OJq9 z50IHhDNEHttfof#Dw-v{dk&F?uXf10R6+C@&#oY zx40RyIA%h0>VF<2-a)+LBvEq?@&*$?T^Jd>Cp;B#ltx!Ix?scTcv{x)Ja*Umthgqa zUBHf#FRZ*=9a<7b7z&cBmd|3-R)FRk*oA=;XDjk} zzM-*UW1TR%r)g&QztjR3My1hm12oTvAE+a22mDMtVZCR}?_YLsYhFo5?q-5+wi^v&|0_L$N6h) zAz=)fFRa%uI1c(?j7K#u5ADi0PC1~tyy7v^rUvhLvFlUAZkC2$*AOZ+rXN&gNGiGb z{?dVn2=52S2qKoP!?*vr%zyTEeR;2AJ^K-82=m31ghh-FuB({}L)h;~5IGu2@-;k! z_Flq2LOl2}!dR<75VT?vYTQCC)Ekkn2!gP&I=jfqW5z1D zHJ(NpAL5mSt(yM*ebO14EzX;pa-_`(OGw<3Nih=jy{<6^-qfw6nhQHWku1eX5h8Q= z7m+=NGocEQx;uDfji7Nh-!=-r8}zExcasK-vvgM)iw^uIzIK`+HTpKJR{NRax5V4k zh-ny~rj#pfzSJJxFQ=a%cUBSCnCGLdGewu_={30$PiD%+(sri3jmy`uoxFiCWOYj*7L4s-Q~xfUZP`1jmIg0numwXGd|ON4Sx;y#U!Eel{kFkjV6SUjw9{vo_fy~ z{nK4Ze9-3@K8hyL$5S5Hs&7JsFl($G+b7IB`Jd^~2}FG=^gf+lq0_>vY&c)HVJg57 zjKTGabPduN-S>?DciIRWWs{ktqqd<*aht50hF#Ni?(XYxJh~C1)2qafYS7ro=$T%js5_xP6lq zl30Vc*cMH7&X06IHVX>fiZiF>9xG?os>9bI9*#gjS1m};af^s2^lbLKaMWFds}>Q-HKUd-4N;zEEYK->AYHOV7}B!{vySIt8s_ zg3Kc3lEUvV(>PkT#tAxo1`&n70oxp+nUuaWBH4M$pn$z0RP3wmHZEtZu_3jJNF&Yu z%o_%*fP6RnTQ=B%*S{2HmGQDMcC6r<;5vn()GQK9Yp<=7c274$c8=+EHz59J!?5631*5Gn*(UZa3!vWGI8U~f+H zE_G+@o8Hk?tn|d}A_|DKoUQ3SuJWi|Wv{Qf@1?4iyg>cPMs|xfpvSeRB(%EjcwF`e zE_p!f^_MRh6>j1L@o|h#=G7Mi+x-EvJnx@g-r9+BQVGd;5BTjAoSZT1L zi89z8OdohX!~D&*op?~2u1o7pm1JX6JtS2YtQ_Z``ek;#ae)`8>S$St@ZoU|pydiq3#FXFU0bwS2`h!@ua z{|a}&^APs;_}c*s^V~xtK$-fEaUHauNp-A2bF%^{VH!I|*$=CBEPI8;%ewg%Jk2cJ z*~4pS=rEMWn}lz);5xNFKulm3{7Wwfv4{uo%D?5U*hhxvJXdyKl;Cd@&ETc zcv5}V;8iamXnx$PaR{?yPle;7kbW)w0(=u{fJ(rL4G6aZX}vq@*&0ZPEetJPT7}@*y4JliIGFy5B8zYt*1wr>BMYX!Eg=X=@)PQIy?qG@I_a2)QuxK^N5O=OzyC$xu3q z8PvYlfElwqu*=)TDn!3BYP9OGHl=2^diVGcW<1Cydh5{o z)gv1rLg*6Cb`L1zA-dTzw6HFhjqvJRVnkkqf;Yb8iW81P)smbZdW0}Wf3Z%!O;;YM zhj>Ybi_p5Y(U-Rgl`ju9FHLHNoH;SXcH#^#dqAtg(0!#VBC(8)7cIY#~e-YWv;x8&7- zR4qx&S~#H|<-4i3*Nso|D5*sS<)q=6Qg=~w>XZ1kRe*f>NXeNqBE<>yJwny)%y!gu z$?RSEL|4X-_pJHI_7N5>zI4;9RpSSI_1U(d&EllSS3k^C5?Jy#g1QN}7Bcs^dETp` z^~$#%GITT0y1WYY^RT{P2f0N59off{paz--Hj4+%k~!WvT#Nn)e`J_@LCWSBfobDB z1=Y)@X9X#_$DGYtQ+Jp>IvdC*<$RgoF3~)3Qoe3w)5on!Y_ndAa!JRQcervo;@egN z^Bus$vn}H*iUQX4lONS2^ac|6ui$n^JSRpku+YkrnJ#%||B;jZTrOza8a34l-+^af zIKCY||A_P!AKb7s#rgq>pNC`9)@mUQBtxJw!C_onEL!wx6UKO4QwskBJ_A{X64>IO>BG7W-o5oNdNK5$7c3N0 zKF|^=hlzVR-_kG`dxoa4QIlFo@I+#c_MJAYBtmpc-;1g@zG z5v^&1A>@rtHMy(_NpCfV-rFBC)^>cWw0uttfR&mcE2iXB+iMNhrYcoDl#!MlO8Ej& zpf6!1swx#k80567=vgIG=2ncj(7AU!1^OT0T#iAvt92= z3TvY9!wr`od)MfvIc=4PjVbn@c!)i3%$^!|W0WyUc3=7C9J2&V#a&h=PCo!=%juOR zsB`GV9oQhIUHq1F0d~}6je&83E;-aVlh08X)J66A1s9Y;lHZBsHu_v zw+UunD8FjhbjR7zHA>g#ZgNga++wcm)3mAYz$cN}bII3#>94N(H2cjs!+06B97x)} zMIp-Y%#ufZC*9RY7%#kO81JT4p~fD-*z|5~C5Ly{py-n7Z+zR+IV#MiJRhW%X052MCR`p(TTWCA;b++`5Zacrp*>A=rg)N_YS3I1TRrq`0`(nx*DLkb4^(y!OKkj=CI%h$-Cg`nHN(B-oXt{>xOd@^VroX}f$uKeI#iau zTd|3t@CeuA7_W*Xk&m4ol*orO)K4GTklmchu7)IR;y3=Xl|g(M<+^?PD9u+ze%>ur zK1!!X&h_g;Evts9hlbWtlZh99%~X4keyxZ3;B6aK_Af(PUBy);ugH|nC2#I8kl2z0 z!|MDJ?tEV+R>c8%nL>nltlZn0Ar}MNj%gW}^Kmw`t8ic-996yIJAn0VnoYnLXnA;g z6YKK(o1S@OECn+X@{NAP(Wx(?3pOrqPbY4&Tv(LaE$DWe#+|4^f+UXq0)mE}vQ!%- z&)^tF9@06Yo+)X9iDJ@iEi`5k&yT;9qGZ$#o_EviIK`k+^m+Kdd;lZvc!CW%d772W zbyifM9P&C0ajJ~siPX6^MoK&}Q`e2OpQu$!=qCM`RIL3;>S6LD-b>DHkyT|+dI_H! zwz+psX@9h*&h}Gz^RokC@;fMARqA}sZGDf_xqIoCe!e!TMM=Bkteq#Om>l(4Wa)TJ z+J>2@{k;no-Yu6uy!P|L`v$!FPvrCvgex_eVK+2Bm4Uc#oUy=BX(} zTyH$xtRs-F$=s!I7b6U`Ks^~zb|rC!#MnN&iJc7MO@@{7bZ|}XDek%G!W2GSllH0& zgLcM7DLpHb8s4IPWVBO`NiLSsB;imzc1r9jD3)M?VYSX3{ecAU*%3Jxxnl zkHUH1_dL~`ei&(vra>1l zAV!W+AN9U7ODU5?(gay^wMj%x9b$VgDT2^I_LkKj)w^dO*07;H5Ehgi>rRi-yn^#! z8e`xGV~n~ajD8f4qt#E)gOsCiAvjOohg@`Rxvgydi{~9d1}o>)knxdC0IymG(VA?h z^Rbwo0poCO7>{ed&00U=08+7ed*`pUQ>eoE?3r=S&_s=m{YtRx3@7RmWI;ULn#-vB|&Flv0H zX2cu9GpV5n1BdErf=Smz*%;y}YInHSsKcR);uADw(jzkzhRazwGF4#c;S|Q3!g_o=fN;qZrEaoFOlt O^gkGUfc1Iw+5Z8IF5@r& literal 0 HcmV?d00001 diff --git a/__tests__/plots/api/chart-render-update-non-animation.ts b/__tests__/plots/api/chart-render-update-non-animation.ts new file mode 100644 index 0000000000..7f86c7df68 --- /dev/null +++ b/__tests__/plots/api/chart-render-update-non-animation.ts @@ -0,0 +1,53 @@ +import { Chart } from '../../../src'; + +export function chartRenderUpdateNonAnimation(context) { + const { container, canvas } = context; + + // button + const button = document.createElement('button'); + button.innerText = 'Rerender'; + container.appendChild(button); + + // wrapperDiv + const wrapperDiv = document.createElement('div'); + container.appendChild(wrapperDiv); + + const chart = new Chart({ + theme: 'classic', + container: wrapperDiv, + canvas, + }); + + const options = { + type: 'interval', + data: [ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, + ], + encode: { + x: 'genre', + y: 'sold', + }, + animate: false, + }; + + chart.options(options); + + const finished = chart.render(); + + let resolve; + const refreshed = new Promise((r) => (resolve = r)); + + button.onclick = () => { + chart.options({ + ...options, + type: 'point', + }); + chart.render().then(resolve); + }; + + return { chart, button, finished, refreshed }; +} diff --git a/__tests__/plots/api/index.ts b/__tests__/plots/api/index.ts index 3a7fad70f0..0d908f12d6 100644 --- a/__tests__/plots/api/index.ts +++ b/__tests__/plots/api/index.ts @@ -21,3 +21,4 @@ export { chartEmitItemTooltip } from './chart-emit-item-tooltip'; export { chartEmitSeriesTooltip } from './chart-emit-series-tooltip'; export { chartEmitPieTooltip } from './chart-emit-pie-tooltip'; export { chartRenderUpdateAttributes } from './chart-render-update-attributes'; +export { chartRenderUpdateNonAnimation } from './chart-render-update-non-animation'; diff --git a/src/runtime/plot.ts b/src/runtime/plot.ts index bd3226f45f..ddfa7671ff 100644 --- a/src/runtime/plot.ts +++ b/src/runtime/plot.ts @@ -823,7 +823,10 @@ async function plotView( maybeFacetElement(this, parent, origin); const node = shapeFunction(data, index); const animation = updateFunction(data, [this], [node]); - if (animation === null) copyAttributes(this, node); + if (animation === null) { + if (this.nodeName === node.nodeName) copyAttributes(this, node); + else this.parentNode.replaceChild(node, this); + } return animation; }); }),