Skip to content

Commit 66d625d

Browse files
committed
VueUiTreemap new component
1 parent a07ddce commit 66d625d

File tree

3 files changed

+110
-68
lines changed

3 files changed

+110
-68
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vue-data-ui",
33
"private": false,
4-
"version": "2.0.66",
4+
"version": "2.0.67",
55
"type": "module",
66
"description": "A user-empowering data visualization Vue components library",
77
"keywords": [
@@ -84,6 +84,7 @@
8484
"sass": "^1.57.1",
8585
"vite": "^4.5.3",
8686
"vitest": "^0.34.1",
87-
"vue": "^3.3.4"
87+
"vue": "^3.3.4",
88+
"vue-data-ui": "file:../vue-data-ui"
8889
}
8990
}

src/components/vue-ui-treemap.vue

Lines changed: 105 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,8 @@ const isZoom = ref(false);
236236
237237
function zoom(rect) {
238238
if(isZoom.value) {
239-
viewBox.value.startX = 0;
240-
viewBox.value.startY = 0;
241-
viewBox.value.width = svg.value.vbWidth;
242-
viewBox.value.height = svg.value.vbHeight;
243239
emit('selectDatapoint', undefined);
244240
} else {
245-
viewBox.value.startX = rect.x0;
246-
viewBox.value.startY = rect.y0;
247-
viewBox.value.width = rect.x1 - rect.x0;
248-
viewBox.value.height = rect.y1 - rect.y0;
249241
emit('selectDatapoint', rect);
250242
}
251243
isZoom.value = !isZoom.value;
@@ -283,6 +275,8 @@ const legendConfig = computed(() => {
283275
});
284276
285277
function segregate(rect) {
278+
isZoom.value = false;
279+
selectedRect.value = null;
286280
if(segregated.value.includes(rect.id)) {
287281
segregated.value = segregated.value.filter(s => s !== rect.id)
288282
} else {
@@ -467,51 +461,106 @@ defineExpose({
467461
data-cy="treemap-svg" :viewBox="`${viewBox.startX} ${viewBox.startY} ${viewBox.width} ${viewBox.height}`"
468462
:style="`max-width:100%; overflow: hidden; background:${treemapConfig.style.chart.backgroundColor};color:${treemapConfig.style.chart.color}`">
469463

470-
<g v-for="(rect, i) in squarified">
464+
<g v-for="(rect, i) in squarified">
471465
<defs v-if="treemapConfig.style.chart.layout.rects.gradient.show">
472466
<radialGradient :id="`tgrad_${rect.id}`" gradientTransform="translate(-1, -1) scale(2, 2)">
473467
<stop offset="18%" :stop-color="rect.color"/>
474468
<stop offset="100%" :stop-color="lightenHexColor(rect.color, treemapConfig.style.chart.layout.rects.gradient.intensity / 100)"/>
475469
</radialGradient>
476470
</defs>
471+
</g>
472+
473+
474+
<g v-for="(rect, i) in squarified">
475+
<rect
476+
:x="rect.x0"
477+
:y="rect.y0"
478+
:height="getHeight(rect)"
479+
:width="getWidth(rect)"
480+
:fill="treemapConfig.style.chart.layout.rects.gradient.show ? `url(#tgrad_${rect.id})` : rect.color"
481+
:rx="treemapConfig.style.chart.layout.rects.borderRadius"
482+
:stroke="selectedRect && selectedRect.id === rect.id ? treemapConfig.style.chart.layout.rects.selected.stroke : treemapConfig.style.chart.layout.rects.stroke"
483+
:stroke-width="selectedRect && selectedRect.id === rect.id ? treemapConfig.style.chart.layout.rects.selected.strokeWidth : treemapConfig.style.chart.layout.rects.strokeWidth"
484+
@click="zoom(rect)"
485+
@mouseenter="() => useTooltip({
486+
datapoint: rect,
487+
seriesIndex: i,
488+
})"
489+
@mouseleave="!isZoom ? selectedRect = null : ''; isTooltip = false"
490+
:style="`opacity:${selectedRect ? selectedRect.id === rect.id ? 1 : treemapConfig.style.chart.layout.rects.selected.unselectedOpacity : 1}`"
491+
class="vue-ui-treemap-rect"
492+
/>
493+
494+
<foreignObject
495+
:x="rect.x0"
496+
:y="rect.y0"
497+
:height="getHeight(rect)"
498+
:width="getWidth(rect)"
499+
class="vue-ui-treemap-cell-foreignObject"
500+
v-if="!isZoom"
501+
>
502+
<div style="width: 100%; height: 100%" class="vue-ui-treemap-cell">
503+
<div
504+
class="vue-ui-treemap-cell-default"
505+
v-if="treemapConfig.style.chart.layout.labels.showDefaultLabels && (rect.proportion > treemapConfig.style.chart.layout.labels.hideUnderProportion || isZoom)" :style="`width:calc(100% - ${calcFontSize(rect) / 1.5}px);text-align:left;line-height:${calcFontSize(rect)}px;padding:${calcFontSize(rect) / 3}px; color:${adaptColorToBackground(rect.color)}`"
506+
>
507+
<span :style="`width:100%;font-size:${calcFontSize(rect)}px;`">
508+
{{ rect.name }}
509+
</span><br>
510+
<span :style="`width:100%;font-size:${calcFontSize(rect)}px;`">
511+
{{ dataLabel({
512+
p: treemapConfig.style.chart.layout.labels.prefix,
513+
v: rect.value,
514+
s: treemapConfig.style.chart.layout.labels.suffix,
515+
r: treemapConfig.style.chart.layout.labels.rounding
516+
}) }}
517+
</span>
518+
</div>
519+
<slot
520+
name="rect"
521+
v-bind="{
522+
rect,
523+
shouldShow: rect.proportion > treemapConfig.style.chart.layout.labels.hideUnderProportion || isZoom,
524+
fontSize: calcFontSize(rect),
525+
isZoom,
526+
textColor: adaptColorToBackground(rect.color)
527+
}"/>
528+
</div>
529+
</foreignObject>
530+
</g>
531+
532+
533+
<g v-if="isZoom">
477534
<rect
478-
:x="rect.x0"
479-
:y="rect.y0"
480-
:height="getHeight(rect)"
481-
:width="getWidth(rect)"
482-
:fill="treemapConfig.style.chart.layout.rects.gradient.show ? `url(#tgrad_${rect.id})` : rect.color"
535+
:x="treemapConfig.style.chart.padding.left * 2"
536+
:y="treemapConfig.style.chart.padding.top * 2"
537+
:width="svg.vbWidth - (treemapConfig.style.chart.padding.left * 2) - (treemapConfig.style.chart.padding.right * 2)"
538+
:height="svg.vbHeight - treemapConfig.style.chart.padding.top - treemapConfig.style.chart.padding.bottom"
539+
:fill="treemapConfig.style.chart.layout.rects.gradient.show ? `url(#tgrad_${selectedRect.id})` : selectedRect.color"
483540
:rx="treemapConfig.style.chart.layout.rects.borderRadius"
484-
:stroke="selectedRect && selectedRect.id === rect.id ? treemapConfig.style.chart.layout.rects.selected.stroke : treemapConfig.style.chart.layout.rects.stroke"
485-
:stroke-width="selectedRect && selectedRect.id === rect.id ? treemapConfig.style.chart.layout.rects.selected.strokeWidth : treemapConfig.style.chart.layout.rects.strokeWidth"
486-
@click="zoom(rect)"
487-
@mouseenter="() => useTooltip({
488-
datapoint: rect,
489-
seriesIndex: i,
490-
})"
491-
@mouseleave="!isZoom ? selectedRect = null : ''; isTooltip = false"
492-
:style="`opacity:${selectedRect ? selectedRect.id === rect.id ? 1 : treemapConfig.style.chart.layout.rects.selected.unselectedOpacity : 1}`"
493-
class="vue-ui-treemap-rect"
541+
:stroke="treemapConfig.style.chart.layout.rects.selected.stroke"
542+
@click="zoom(selectedRect)"
543+
class="vue-ui-treemap-cell-zoom"
494544
/>
495545
<foreignObject
496-
:x="rect.x0"
497-
:y="rect.y0"
498-
:height="getHeight(rect)"
499-
:width="getWidth(rect)"
546+
:x="treemapConfig.style.chart.padding.left * 2"
547+
:y="treemapConfig.style.chart.padding.top * 2"
548+
:width="svg.vbWidth - (treemapConfig.style.chart.padding.left * 2) - (treemapConfig.style.chart.padding.right * 2)"
549+
:height="svg.vbHeight - treemapConfig.style.chart.padding.top - treemapConfig.style.chart.padding.bottom"
500550
class="vue-ui-treemap-cell-foreignObject"
501-
v-if="!isZoom"
502551
>
503552
<div style="width: 100%; height: 100%" class="vue-ui-treemap-cell">
504553
<div
505554
class="vue-ui-treemap-cell-default"
506-
v-if="treemapConfig.style.chart.layout.labels.showDefaultLabels && (rect.proportion > treemapConfig.style.chart.layout.labels.hideUnderProportion || isZoom)" :style="`width:calc(100% - ${calcFontSize(rect) / 1.5}px);text-align:left;line-height:${calcFontSize(rect)}px;padding:${calcFontSize(rect) / 3}px; color:${adaptColorToBackground(rect.color)}`"
555+
v-if="treemapConfig.style.chart.layout.labels.showDefaultLabels" :style="`width:calc(100% - ${treemapConfig.style.chart.layout.labels.fontSize/ 1.5}px);text-align:left;line-height:${treemapConfig.style.chart.layout.labels.fontSize}px;padding:${treemapConfig.style.chart.layout.labels.fontSize / 3}px; color:${adaptColorToBackground(selectedRect.color)}`"
507556
>
508-
<span :style="`width:100%;font-size:${calcFontSize(rect)}px;`">
509-
{{ rect.name }}
557+
<span :style="`width:100%;`">
558+
{{ selectedRect.name }}
510559
</span><br>
511-
<span :style="`width:100%;font-size:${calcFontSize(rect)}px;`">
560+
<span :style="`width:100%;`">
512561
{{ dataLabel({
513562
p: treemapConfig.style.chart.layout.labels.prefix,
514-
v: rect.value,
563+
v: selectedRect.value,
515564
s: treemapConfig.style.chart.layout.labels.suffix,
516565
r: treemapConfig.style.chart.layout.labels.rounding
517566
}) }}
@@ -520,43 +569,18 @@ defineExpose({
520569
<slot
521570
name="rect"
522571
v-bind="{
523-
rect,
524-
shouldShow: rect.proportion > treemapConfig.style.chart.layout.labels.hideUnderProportion || isZoom,
525-
fontSize: calcFontSize(rect),
572+
rect: selectedRect,
573+
shouldShow: selectedRect.proportion > treemapConfig.style.chart.layout.labels.hideUnderProportion || isZoom,
574+
fontSize: calcFontSize(selectedRect),
526575
isZoom,
527-
textColor: adaptColorToBackground(rect.color)
576+
textColor: adaptColorToBackground(selectedRect.color)
528577
}"/>
529578
</div>
530579
</foreignObject>
531580
</g>
532581
<slot name="svg" :svg="svg"/>
533582
</svg>
534583

535-
<div v-if="isZoom" class="vue-ui-treemap-zoom-info">
536-
<div v-if="treemapConfig.style.chart.layout.labels.showDefaultLabels">
537-
<span :style="`width:100%; color: ${adaptColorToBackground(selectedRect.color)}`">
538-
{{ selectedRect.name }}
539-
</span><br>
540-
<span :style="`width:100%; color: ${adaptColorToBackground(selectedRect.color)}`">
541-
{{ dataLabel({
542-
p: treemapConfig.style.chart.layout.labels.prefix,
543-
v: selectedRect.value,
544-
s: treemapConfig.style.chart.layout.labels.suffix,
545-
r: treemapConfig.style.chart.layout.labels.rounding
546-
}) }}
547-
</span>
548-
</div>
549-
<slot
550-
name="rect"
551-
v-bind="{
552-
rect: selectedRect,
553-
shouldShow: selectedRect.proportion > treemapConfig.style.chart.layout.labels.hideUnderProportion || isZoom,
554-
fontSize: calcFontSize(selectedRect),
555-
isZoom,
556-
textColor: adaptColorToBackground(selectedRect.color)
557-
}"/>
558-
</div>
559-
560584
<Skeleton
561585
v-if="!isDataset"
562586
:config="{
@@ -572,7 +596,7 @@ defineExpose({
572596

573597
<!-- LEGEND & LEGEND SLOT -->
574598
<Legend
575-
v-if="treemapConfig.style.chart.legend.show && !isZoom"
599+
v-if="treemapConfig.style.chart.legend.show"
576600
:legendSet="legendSet"
577601
:config="legendConfig"
578602
:id="`treemap_legend_${uid}`"
@@ -666,4 +690,21 @@ defineExpose({
666690
align-items:center;
667691
justify-content:center;
668692
}
693+
694+
.vue-ui-treemap-cell-zoom {
695+
animation: zoom-cell 0.2s ease-in forwards !important;
696+
transform-origin: center;
697+
}
698+
699+
@keyframes zoom-cell {
700+
0% {
701+
transform: scale(0.8,0.8);
702+
opacity: 0;
703+
filter:drop-shadow(0px 12px 12px black);
704+
}
705+
100% {
706+
transform: scale(1, 1);
707+
opacity: 1;
708+
}
709+
}
669710
</style>

0 commit comments

Comments
 (0)