From 4fcf7b889b27b14db779d717c2e3e684d0845198 Mon Sep 17 00:00:00 2001 From: MiniPear Date: Tue, 30 May 2023 17:34:16 +0800 Subject: [PATCH] feat(interaction): emit legend filter --- .../api-chart-emit-legend-filter.spec.ts | 56 +++++++++++-- .../api/chart-emit-legend-filter/step0.png | Bin 8759 -> 9916 bytes .../api/chart-emit-legend-filter/step1.png | Bin 0 -> 11296 bytes .../plots/api/chart-emit-legend-filter.ts | 75 ++++++------------ site/docs/spec/interaction/legendFilter.zh.md | 28 +++++++ site/examples/component/legend/demo/custom.ts | 30 ++++--- src/interaction/legendFilter.ts | 59 +++++++++++--- 7 files changed, 165 insertions(+), 83 deletions(-) create mode 100644 __tests__/integration/snapshots/api/chart-emit-legend-filter/step1.png diff --git a/__tests__/integration/api-chart-emit-legend-filter.spec.ts b/__tests__/integration/api-chart-emit-legend-filter.spec.ts index cdc38fde84..9b5b6a1f61 100644 --- a/__tests__/integration/api-chart-emit-legend-filter.spec.ts +++ b/__tests__/integration/api-chart-emit-legend-filter.spec.ts @@ -2,27 +2,67 @@ import { chartEmitLegendFilter as render } from '../plots/api/chart-emit-legend- import { createNodeGCanvas } from './utils/createNodeGCanvas'; import { sleep } from './utils/sleep'; import { kebabCase } from './utils/kebabCase'; +import { createPromise, dispatchFirstShapeEvent } from './utils/event'; import './utils/useSnapshotMatchers'; +import './utils/useCustomFetch'; +import { LEGEND_ITEMS_CLASS_NAME } from '../../src/interaction/legendFilter'; describe('chart.emit', () => { const dir = `${__dirname}/snapshots/api/${kebabCase(render.name)}`; const canvas = createNodeGCanvas(800, 500); - let chart; - it('chart.emit("legend:filter", options) should filter channel', async () => { - const values = render({ + it('chart.on("legend:filter") should receive expected data.', async () => { + const { chart, finished } = render({ canvas, container: document.createElement('div'), }); - chart = values.chart; - await values.finished; + await finished; await sleep(20); - // Click legend item. - const [item] = values.items; - item.dispatchEvent(new CustomEvent('click')); + // chart.emit('legend:filter', options) should trigger slider. + chart.emit('legend:filter', { + data: { channel: 'color', values: ['Sports', 'Strategy'] }, + }); await sleep(20); await expect(canvas).toMatchCanvasSnapshot(dir, 'step0'); + + // chart.emit('legend:end', options) should reset. + chart.emit('legend:end', {}); + await sleep(20); + await expect(canvas).toMatchCanvasSnapshot(dir, 'step1'); + + chart.off(); + + // chart.on("legend:end") should be called. + const [end, resolveEnd] = createPromise(); + chart.on('legend:end', (event) => { + if (!event.nativeEvent) return; + resolveEnd(); + }); + dispatchFirstShapeEvent(canvas, LEGEND_ITEMS_CLASS_NAME, 'click', { + nativeEvent: true, + }); + dispatchFirstShapeEvent(canvas, LEGEND_ITEMS_CLASS_NAME, 'click', { + nativeEvent: true, + }); + await sleep(20); + await end; + + // chart.on("legend:filter") should receive expected data. + const [filter, resolveHighlight] = createPromise(); + chart.on('legend:filter', (event) => { + if (!event.nativeEvent) return; + expect(event.data).toEqual({ + channel: 'color', + values: ['Strategy', 'Action', 'Shooter', 'Other'], + }); + resolveHighlight(); + }); + dispatchFirstShapeEvent(canvas, LEGEND_ITEMS_CLASS_NAME, 'click', { + nativeEvent: true, + }); + await sleep(20); + await filter; }); afterAll(() => { diff --git a/__tests__/integration/snapshots/api/chart-emit-legend-filter/step0.png b/__tests__/integration/snapshots/api/chart-emit-legend-filter/step0.png index aa0752c1ae844abb2b6c1f8b89ddb4f7795e37fe..2c261813da22468a363a5f377ec976dba8890aff 100644 GIT binary patch literal 9916 zcmeHtcTiJnzwSx`N$4Ob3MkT1s?v*qv0x~oC?GvCHr=ZZ`rNq)3&m!bYm} z&Js4FB1L*nvMnH?L?RF=;jHZMoS8fKp1E_*AK%>j&74UlnY`;=Z~2wyd46x!{c~rn zMFeF80RRxeo;m3V0B{lj!02cs)MD^)>NE6({KeM#B(TGKJ#8sW0f2)5_T=%4k=cvW z5g8uCm)E~9=ll+bV-G&$`(641#qO28x^@QcHoH*)fBrR}9O_I*(qjEXPU2sDYS$FV zQq}|+)ynFoF;&BQ+yfX&7mg_S^Y>qq_|Cuu@J@wO>&Z7G?goA-wvS(L=e*cA=#_OHqZ z{Ya0%qd3eO+Xm+=G^!_{4i~E?K5-AUovbenV}3RaPQNdymV2q_qQ#SfZyxkFTK1L^ zOH)`ZRjSY-k8Ab9u_1JQI-+eqCyHwj=Tp|YF`w_#m9%YF( z*<$y3yB1y4_N)t;E(N!oORKKYsso-(1};rC_(>;p;=yik9+OWz=itznf~9&)4-XHI zZfypwT0DB5^YQFHz>hn<5n8cA;C}D#sR_#EFM)9d&ybI@3c(l>p{C+D0{m{p{>%6` z&u*Zm-!xeFjEw|OjWhw`c!MY#%(bNpJ|b){O()ODL^y5oA7ct z-~1#o*s$opPY>G$SfEPsF_IByZRv#jqA-eiAn4J;xNKoO(1KqUsfqEeh7aL)bC$I zI!oM=u;Q;rjvbTbs`X*d?QKHlbNq|InhG+Fu!r0ex}`UMsN#9`WXW6<)1-bB+FOgy@k~l zl8s;va9dIrsWoV8x9jvSIvdO`5pBrO^Xtt8U#&)O>vjI}y||^N1r;6^b__-A5HVV) zjb5FnA(L#WSDZ2nj^Q&4AX7bnVmmiC_Y3&;g>AY8dh2CfT|{Jy7mc&;4E6IHcCXp8 z9{`OaJrYo(mZEGTvRBCb$K12zc%P9H*VX1)EiAQVP=A`!)cTofdzk&Tr%Ba*klV+b zoCFO^gP(?sgetJlT1!;M4rm2+lYF60X8G4>%Gm1{sLHd@XBs&?X$uO2R0Ad53VDOR_|Go*nO5aeF=o+HdXA(m!+kpb^UD%)TCPHSwgaM zjcqxrbPWbMN;1MjNuyN){BKipI*+3ua{Yh%w~3_sFuO znV@5AavmTp2_NtUb;z`L_{j~C+C(v<;nG(#LL@PXTN7OZoAeW4J?v{1X3mYP$kMTr zR$v`RKYS6yMOA)DR-`m<%M_R?%J!~q{dv71HafFFtS94$k85T@8{gSw9rvoMJ*R;3 zmbHn(LH(A3bLv~%UnP_dAeQW?SK_J4mRRcNgO~_Y$X$w0Td%yMI!FuNDIUyUYTDR;rD+PI|YCl;9m&h7n=ri2FoZPims9(GufL9Kx<>lqq>vM0Tz7mscDe zD;ENRu(KQylvyCJooZtQ-NSFPboa!|;rVi{w&LQz^O*(3f_K_A?89ajEXI%5T2m(! zYk_)kjuNJOCKA)%@SFYdq>>;Ng^Ve|?2~h+kL{j=jYzuv3_;9H=+ctO-hc*4gpyV# zVwKqM7#?ZZlfE)mfxI2;Q&SX@xVogo_c{bKXQr+pe*}#6yV@;(*8foK!wMZ63dulD77o~3>sVszYF_Xr>NWi~Z7?oq*Bmleq) zN4IdFm6esvsygIuDY7o+pBppl6JgHJyP>zvQ%qTD0MCtV{LBL#8I`%pG_)Z7p2^#S?9qj(4op@UxwXW=9Y(H z&%oVp=?Ijh8|g5mY&bp;4J-EcaeY=U(c8VbA16lN9M^zCEiqAs8MiAxYfmPA9sSR{3_+Ht7aVpV@jJZ(Kd-Ap|4nh=voFliR$Xy&_z$}j>ZnuB@_ zMU@pOf0hF`ZT%PJj)I{~f&A~$nC`!vC}{(Q&&rE~T(R+R0 znZZ!oJo1!OLgy2FX2_PO_w{!wshIqVPTDH8`4CiE6xyeU{dUG2JvQ<($z&5%37*#?;KIu|6@0 z#>>)@ZtqqqUj#3dPad~tzo0zbbjFY(V+^@g7^cmqSW7_rVD_@{UGaeOgF&NO;Ibr! z;m%pry^dmJzn)o~?teWM%`APPVw;wI+MhiAhg<24r{*5ZFc5~?viA0-_24t(gCN$Y zK@ik6%3M7^n|G7@9)fHUELD!(Lx{ie$-?y01HG3#zIbs-(`yPc<20ltEbIqUAlUh8 zfoRa!lVAjKPC{c-)4FD=O~U-@Mh29lJzZsOP?wOZ~Iy>6wo*JzNDQ9j8oe|7G~(8y$(k5z_K79TwizhBBv zv|#*|BmkOFgd|#DGYL<=(ztb;i~RB!}Ko$@TYxCddrHs&+R<5%)}0Y2Ia3Z`Gaet6OiqbfIK zi7&w*)N4C4s9#r{1%t5XD3s+IDaudIK`95}zx89A7X-T;(^YrGut0rX+u7T}-8kRG z&8zc6MY5JC$Wcy37h5MFjkaS_U*}wG5MO)!BlN58YEPyPguGT%$)s~_U)ZFyF$o=H!t_hj)iXSg@pDZ<~_x^E#Lmry zLJ&1gI=t}!wbsG+?ZfY*+s6k+zeS%JNcz41o8TF$a#4#g2@>~@jsP}P7^ZY)uMNcKRwNM4o* zjn6}DLG%IA%RggX1xMR6%yS;X-w9Y)-$RGvELejh9*(Jpl&|0x!MU~eGWYPg z1GoljLlMj2-#0`9h6nDvIMyXMo#cdl|8YPqMC0SeryS)POpT;Q@G$J!UdC425ztb+ zF?O>jFmgwcsFvRyY4LEE8{Fl}mnMV;>QcP-ATe&UxY_qaxa@G+>Y4YWtn-rd)!*tB zux7WN`9UGlFgQ%nxVf21c7W~hmArqmXg@b!3iOG$<91Tp2#TR%M($I;N4F}Rh>*Xa zw)khJO3lEpaiT_mjpJ=+K2VW(m?%#?-@#EsPqzl5XVEiAIY15-tC#il9%$FTh)a4q z&&CPOL&Exbk3Up_z(z%N7&S9fUV*1pbWN2k#(HljRXDp-zWT zr2(*PFHSOqZksHGexM1DnCnwBKzUGdc* zqpGg`V*s^ML6SEtw`WEkO5iQ{-s5uq6a~7`Zo9kG{*pP zsi{sf1-1gEH#?8N&ornLw5V)JotDwqW9fL{7?%=WV&j8cqT5IKB~`w<7BbC$ z?+(DyqDQw6zy3rzK{^EqdOY&)U5L6#02k;&hzHBv@mxX94Z1OgIfEECcR$SABkyW4 z<;D(@{mWYPGhYZx0*>VIYyNA1^uHLV{Fj#d#4#b=NZ444n!qN%k2E^k;gfm_$$Z>#vXBB7pD*3#k&BTwSSz20!YTH zxDO`x)}E4J;l9G%C7%GX**&0p zU;QSJ`L%}TflI#h1mh9$-fh{p(U|lK$Vd~QAI$durgRGU9>BOkLWA4tF%U}O)m#*( zZZ6x7vnEMCWF~2pv`u~oO71V>8QiVxWTaacHHZ^R?+$8oWowN0MZg_u>jHQyJi#_0 zG0_eS{`#VO2Xf~jsdb3Z;{b1faf}(RE#OtxVhKdC)RjRwzy*-Ze6xru!8?TU7FPFFo6aOz!oEtn z?Yuz{VBE@{RcKttvzhL|O>DgyPF`WF1@0kgPWu|oTZUQ>OuRiYzfHs=FI9eGM26Sq z(gR~{gPm4z5BP#mtazk#7LzByvh`751iXrLjC7m4V_lD;-w!TLh332tt)iPEYt^>z zl2!eFyP9dJK*T!6XO_cTWjUIpdU`Gzm<%7_{$xElFMm)~g%5 zcwWKY0PM({GI! zsRpxU}9H04pjig*MAQR=T)J=m8&)dW>Q*YO8HvR!bfTLL_BOt*J|7Z^uWa%#%dCe zvIY%@AWAu8vxp}7RISF!{Q+3Q4xsMBB`eprbK#;vCwOG>`*4yr{RpKZLa0KVV@@>A zFE&yL6J*F_ziHBWJ3v*>{xJRNl%OtXn7=nES3)?c+qf{$pN`ZClNV ztoxCxX7kA*%6+Ez(c`LC>9pD}8IOvp@yE(j*59O(s{~xO*9f?szA&(uqD`}|x+aO9 z6*7!b?lKJ-`D0tv`Hb1CtJqTg_`e8F{vF5HNH@-wTy*)|vIiR_8}%nQ*yL)cU;bszCH_kq@?YS5<$vAB6UTd_ z-h2g!E<_v{LAqz^ro@v99)<3JC7+x?tVlhqUU;nOnE~X%iOw)npcTQ{!%`&5LwMit zAFW4$CFBCad{8$;Lbp|^<`LxVlWLF*P22XE)D1yYi~@rPru4UB59|)8jqViclu#1G zcfC~p;{Wr;`fh<)x!Hj6ZHL{~`=hV?9mF*{S_CL1E(8und#Qc<(?-viE(^W@-v>=u zSLW>u>o2~x?+6wk{nnmOv267-^OV4v-MNi^O)om@a+vLf9{xg(RGwRhEw%Rf$d3yXhr%`tbuE#-C`XLAoX8aIBTuv}{xvb&)?(s-V3IEg z&3US5h9cDYKY352hC-t{7AsTK-pJY2x4o#7 zqz=s;q>JOwGi%uSxo7m}&ijzDqGS6b`Hg|def7KM0vXXsYEycw*L$=tIJVxED*yBq zdN{zB_bdRAhg?IZi6@Db?@AKWAl(Pg86JBS5E#si9T3gu9q(xo4H;J4eRKlJQq??g z!^pik_Zj(_TeBVZXS5OHI3f?p-NWHyoPX};_r-cw`;=@=DI06X*F>t(FivEhe1fWE z$gngOq_h#*$TdJ47N5ZC^t)`h7y>Q>((q-z5qO`Uuk=-R+ymAh?I{ADA5u%UBtfZm zOL7<4K#O)1JIVaKFxxWTXUgEPWOPL{1m(`mNtoU5cZ^i1AVZ&rh%h2Dzm9PY=QtSa z0H1}+^Y`+-42r(HtxK;XKcRej%ZKS^h_@g4EQ;yFVCLRkI%yn^Z8!=9xKyOE?7pRt zTF|J0JK#XcmN`z77eMO_DLiimsg^+j8k;(OT&dKzZHnL&ryT8>o7K&eD1vy^!&j? zH~M+H7#hX74^>&F^gJ}mjpR;p8fS)MD%^qQ#C}XYS$ruT*=*ph3MP+*COO>ckA^Js zKJsY(ZUzcWj0(n4h_ zqsFu+VB0RY%@J7JhmksxxVj~luMO5$=|fF5(}C`0~TC*>xZrbIb~HA_<>OOqxm zT?9C~ED2=m)8g+0E+0m${RSniQ3PS<&3Aei2KVCfmJh|}#G`)4vGVWj)n=q_GW35P z>t*Tq!J^&G=#x#igh)n4!Y*T>tVN^RfBbQkP1Npvd$$rnmaeO4%?AmC;LnpFlhXFiy93fmvp!?tk1fV`Nd$N@ViP8>YJPholAdr|)0!H7=FV9cE9&)XOID1P4r?7O3X0Zd z=0Zo3P=+JYd(isc&SU?Oc#HEhjyzC`1RCnEkTHWy-P{F&b9jDgv;E)d9P47DTx2ed6j;7^Q5Q(!aQQvNoIV4_LB9(f#;x)8>yYt> zu66;^hQd4Y^nu=sr>Nm_Gbm`=L3>$voERoOXn#GGIFk$Y3%{%swH@s7zq<=x$lihF YgaxSRTQ9za9!CSPr_P=%!{BcH8<(Aopa1{> literal 8759 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 J^+V9*{{ZU`F>wF@ diff --git a/__tests__/integration/snapshots/api/chart-emit-legend-filter/step1.png b/__tests__/integration/snapshots/api/chart-emit-legend-filter/step1.png new file mode 100644 index 0000000000000000000000000000000000000000..f95abfcd57012650239e39238bd31b35e666c088 GIT binary patch literal 11296 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 { - const scale = chart.getScaleByChannel('color'); - const { domain, range } = scale.getOptions(); - const excludedValues: any[] = []; - assetValues.items = domain.map((text, i) => { - const span = document.createElement('span'); - const color = range[i]; - - // Items' style. - span.innerText = text; - span.style.display = 'inline-block'; - span.style.padding = '0.5em'; - span.style.color = color; - span.style.cursor = 'pointer'; + chart.on('legend:filter', (e) => { + const { nativeEvent, data } = e; + if (!nativeEvent) return; + console.log(data); + }); - span.onclick = () => { - const index = excludedValues.findIndex((d) => d === text); - if (index === -1) { - excludedValues.push(text); - span.style.color = '#aaa'; - } else { - excludedValues.splice(index, 1); - span.style.color = color; - } - onChange(excludedValues); - }; + chart.on('legend:end', (e) => { + const { nativeEvent } = e; + if (!nativeEvent) return; + console.log('end'); + }); - return span; + button.onclick = () => { + chart.emit('legend:filter', { + data: { channel: 'color', values: ['Sports', 'Strategy'] }, }); + }; - // Mount items. - for (const item of assetValues.items) legend.append(item); - - function onChange(values: any[]) { - const selectedValues = domain.filter((d) => !values.includes(d)); - - // Emit Event. - chart.emit('legend:filter', { - channel: 'color', - values: selectedValues, - }); - } - }); + button1.onclick = () => { + chart.emit('legend:end', {}); + }; - return assetValues; + return { chart, finished }; } diff --git a/site/docs/spec/interaction/legendFilter.zh.md b/site/docs/spec/interaction/legendFilter.zh.md index 2db26c965b..561b8355d5 100644 --- a/site/docs/spec/interaction/legendFilter.zh.md +++ b/site/docs/spec/interaction/legendFilter.zh.md @@ -28,3 +28,31 @@ chart.interaction('legendFilter', true); chart.render(); ``` + +## 案例 + +### 触发交互 + +```js +chart.emit('legend:filter', { + data: { channel: 'color', values: ['Sports', 'Strategy'] }, +}); + +chart.emit('legend:end', {}); +``` + +### 获得数据 + +```js +chart.on('legend:filter', (e) => { + const { nativeEvent, data } = e; + if (!nativeEvent) return; + console.log(data); +}); + +chart.on('legend:end', (e) => { + const { nativeEvent } = e; + if (!nativeEvent) return; + console.log('end'); +}); +``` diff --git a/site/examples/component/legend/demo/custom.ts b/site/examples/component/legend/demo/custom.ts index cb44372b56..aa5997ea6d 100644 --- a/site/examples/component/legend/demo/custom.ts +++ b/site/examples/component/legend/demo/custom.ts @@ -5,18 +5,22 @@ const chart = new Chart({ container: 'container', }); +const data = [ + { genre: 'Sports', sold: 275 }, + { genre: 'Strategy', sold: 115 }, + { genre: 'Action', sold: 120 }, + { genre: 'Shooter', sold: 350 }, + { genre: 'Other', sold: 150 }, +]; + +const colorField = 'genre'; + chart .interval() - .data([ - { genre: 'Sports', sold: 275 }, - { genre: 'Strategy', sold: 115 }, - { genre: 'Action', sold: 120 }, - { genre: 'Shooter', sold: 350 }, - { genre: 'Other', sold: 150 }, - ]) + .data(data) .encode('x', 'genre') .encode('y', 'sold') - .encode('color', 'genre') + .encode('color', colorField) .legend(false); // Hide built-in legends. chart.render().then(renderCustomLegend); @@ -62,11 +66,11 @@ function renderCustomLegend(chart) { for (const item of items) legend.append(item); // Emit legendFilter event. - function onChange(values: any[]) { + function onChange(values) { const selectedValues = domain.filter((d) => !values.includes(d)); - chart.emit('legend:filter', { - channel: 'color', - values: selectedValues, - }); + const selectedData = data.filter((d) => + selectedValues.includes(d[colorField]), + ); + chart.changeData(selectedData); } } diff --git a/src/interaction/legendFilter.ts b/src/interaction/legendFilter.ts index 7bf39060fa..8de206b702 100644 --- a/src/interaction/legendFilter.ts +++ b/src/interaction/legendFilter.ts @@ -52,6 +52,8 @@ function legendFilter( label: labelOf, // given the legend returns the label datum, // given the legend returns the value filter, // invoke when dispatch filter event, + emitter, + channel, state = {} as Record, // state options }, ) { @@ -79,7 +81,7 @@ function legendFilter( ); const items: DisplayObject[] = Array.from(legends(root)); - const selectedValues = items.map(datum); + let selectedValues = items.map(datum); const updateLegendState = () => { for (const item of items) { const value = datum(item); @@ -105,7 +107,7 @@ function legendFilter( restoreCursor(root); }; - const click = async () => { + const click = async (event) => { const value = datum(item); const index = selectedValues.indexOf(value); if (index === -1) selectedValues.push(value); @@ -113,6 +115,22 @@ function legendFilter( if (selectedValues.length === 0) selectedValues.push(...items.map(datum)); await filter(selectedValues); updateLegendState(); + + const { nativeEvent = true } = event; + if (!nativeEvent) return; + if (selectedValues.length === items.length) { + emitter.emit('legend:end', { nativeEvent }); + } else { + // Emit events. + emitter.emit('legend:filter', { + ...event, + nativeEvent, + data: { + channel, + values: selectedValues, + }, + }); + } }; // Bind and store handlers. @@ -124,11 +142,35 @@ function legendFilter( itemPointerout.set(item, pointerout); } + const onFilter = async (event) => { + const { nativeEvent } = event; + if (nativeEvent) return; + const { data } = event; + const { channel: specifiedChannel, values } = data; + if (specifiedChannel !== channel) return; + selectedValues = values; + await filter(selectedValues); + updateLegendState(); + }; + + const onEnd = async (event) => { + const { nativeEvent } = event; + if (nativeEvent) return; + selectedValues = items.map(datum); + await filter(selectedValues); + updateLegendState(); + }; + + emitter.on('legend:filter', onFilter); + emitter.on('legend:end', onEnd); + return () => { for (const item of items) { item.removeEventListener('click', itemClick.get(item)); item.removeEventListener('pointerenter', itemPointerenter.get(item)); item.removeEventListener('pointerout', itemPointerout.get(item)); + emitter.off('legend:filter', onFilter); + emitter.off('legend:end', onEnd); } }; } @@ -168,17 +210,6 @@ export function LegendFilter() { return update(newOptions); }; - if (!legends.length) { - const onFilter = (options) => { - const { values, channel } = options; - filter(channel, values); - }; - emitter.on('legend:filter', onFilter); - return () => { - emitter.off('legend:filter', onFilter); - }; - } - const removes = legends.map((legend) => { const { name: channel, domain } = dataOf(legend).scales[0]; return legendFilter(container, { @@ -192,6 +223,8 @@ export function LegendFilter() { }, filter: (value) => filter(channel, value), state: legend.attributes.state, + channel, + emitter, }); }); return () => {