Skip to content

Commit

Permalink
legend component (#354)
Browse files Browse the repository at this point in the history
  • Loading branch information
SAKURA-CAT authored Feb 27, 2024
1 parent b328478 commit 113d4bc
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 96 deletions.
11 changes: 10 additions & 1 deletion swanlab/server/controller/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,16 @@ def get_tag_data(experiment_id: int, tag: str) -> dict:
# 获取最大值和最小值
max_value = max(data_values)
min_value = min(data_values)
return SUCCESS_200(data={"sum": len(tag_data), "max": max_value, "min": min_value, "list": tag_data})
return SUCCESS_200(
data={
"sum": len(tag_data),
"max": max_value,
"min": min_value,
"list": tag_data,
# 标注此数据隶属于哪个实验
"experiment_id": experiment_id,
}
)


# 获取实验状态
Expand Down
68 changes: 68 additions & 0 deletions vue/src/charts/components/LineChartLegend.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<div class="lc-legend">
<div
class="lc-legend-item"
:style="{ color: item.color }"
v-for="item in items"
:key="item.name"
@mouseenter="handelMouseenter(item)"
@mouseleave="handelMouseleave(item)"
@click="handelClick(item)"
>
<RouterLink :to="'/experiment/' + item.experiment_id">
{{ item.name }}
</RouterLink>
</div>
</div>
</template>

<script setup>
/**
* @description: 折线图图例组件
* @file: LineChartLegend.vue
* @since: 2024-02-27 15:02:13
**/
defineProps({
items: {
type: Array,
default: () => []
}
})
// console.log('items', props.items)
const emit = defineEmits(['hoverin', 'hoverout'])
// ---------------------------------- 悬浮事件 ----------------------------------
const handelMouseenter = (item) => {
emit('hoverin', item)
}
const handelMouseleave = (item) => {
emit('hoverout', item)
}
// ---------------------------------- 点击事件 ----------------------------------
const handelClick = (item) => {
emit('click', item)
}
</script>

<style lang="scss" scoped>
.lc-legend {
max-height: 28px;
min-height: 16px;
@apply overflow-y-auto flex flex-wrap px-3 mb-1 gap-y-0.5 gap-x-2 leading-none text-[12px];
@apply justify-center;
.lc-legend-item {
@apply flex flex-shrink-0 items-center hover:brightness-75;
&:before {
content: '';
display: inline-block;
width: 8px;
height: 2px;
margin-right: 4px;
background-color: currentColor;
}
}
}
</style>
142 changes: 47 additions & 95 deletions vue/src/charts/package/LineChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,24 @@
<!-- x轴坐标单位 -->
<p class="absolute right-5 bottom-10 text-xs text-dimmer scale-90 select-none">{{ xTitle }}</p>
<!-- 图表主体 -->
<LineChartLegend
:items="legend"
@hoverin="(item) => legendHoverin(item, false)"
@hoverout="(item) => legendHoverout(item, false)"
v-if="legend && mutli"
/>
<div class="relative" ref="g2Ref">
<LineChartTooltip ref="tooltipRef" />
</div>
<!-- 放大效果 -->
<SLModal class="p-10 pt-0 overflow-hidden" max-w="-1" v-model="isZoom">
<p class="text-center mt-4 mb-10 text-2xl font-semibold">{{ title }}</p>
<LineChartLegend
:items="legend"
@hoverin="(item) => legendHoverin(item, true)"
@hoverout="(item) => legendHoverout(item, true)"
v-if="legend && mutli"
/>
<div class="relative" ref="g2ZoomRef">
<LineChartTooltip detail ref="tooltipZoomRef" />
</div>
Expand All @@ -43,6 +55,7 @@ import { getTimes } from '@swanlab-vue/utils/time'
import { isApple } from '@swanlab-vue/utils/browser'
import { message } from '@swanlab-vue/components/message'
import LineChartTooltip from '../components/LinChartTooltip.vue'
import LineChartLegend from '../components/LineChartLegend.vue'
// ---------------------------------- 配置 ----------------------------------
const props = defineProps({
Expand Down Expand Up @@ -80,7 +93,7 @@ const gridColor = rootStyle.getPropertyValue('--outline-dimmest')
// 十字准线颜色,通过js获取css变量值
const crosshairsColor = rootStyle.getPropertyValue('--primary-dimmest')
// 线段默认宽度
const lineWidth = 2
const lineWidth = 1.5
// 线段加粗宽度
const thickerLineWidth = 3.5
Expand Down Expand Up @@ -134,28 +147,8 @@ const createChart = (dom, data, config = {}, zoom = false) => {
// 多数据的时候,需要设置seriesField,单数据也可以设置,但是不希望出现label
// seriesField,
colorField,
legend: {
// flipPage: false,
pageNavigator: {
marker: {
style: {
// 非激活,不可点击态时的填充色设置
inactiveFill: '#000',
inactiveOpacity: 0.45,
// 默认填充色设置
fill: '#000',
opacity: 0.8,
size: 8
}
},
text: {
style: {
fill: '#ccc',
fontSize: 8
}
}
}
},
// 自己写图例
legend: false,
// 多数据的时候颜色通过回调拿到,colors应该自带getSeries方法
color: ({ series }) => {
return colors.getSeriesColor(series, source.indexOf(series))
Expand Down Expand Up @@ -249,7 +242,7 @@ const createChart = (dom, data, config = {}, zoom = false) => {
}
}
},
// 图例相关
// 悬浮提示相关
tooltip: {
// 在此处完成悬浮数据提示的格式化
// 如果需要自定义浮窗,可以用下面的customContent
Expand Down Expand Up @@ -286,7 +279,9 @@ const createChart = (dom, data, config = {}, zoom = false) => {
width: undefined,
autoFit: true,
// 开启一些交互
interactions: [{ type: 'hover-cursor' }],
// interactions: [{ type: 'element-active' }],
// 图例相关
// 平滑曲线
smooth: false,
animation: false,
Expand Down Expand Up @@ -334,6 +329,7 @@ const createChart = (dom, data, config = {}, zoom = false) => {
*/
const format = (data) => {
// 如果source的长度小于1,抛出错误
console.log(data)
if (source.length < 1) throw new Error('source length must be greater than 1')
// 新的数据,遍历得到
const d = []
Expand All @@ -352,7 +348,15 @@ const format = (data) => {
d.sort((a, b) => a[xField] - b[xField])
// console.log('d', d)
// console.log('data', data)
// 如果source的长度大于1,需要设置seriesField
// 依据source生成legend,排序依据是source,数据结构:[{name, color}]
const items = []
for (const s of source) {
if (props.chart.error && props.chart.error[s]) continue
if (!data[s]) continue
items.push({ name: s, color: colors.getSeriesColor(s, source.indexOf(s)), experiment_id: data[s].experiment_id })
}
legend.value = items
// console.log('legend', legend.value)
return { d, config: mutli ? { seriesField } : { color: colors[0] } }
}
Expand Down Expand Up @@ -627,6 +631,22 @@ const restoreByTagLinkage = (zoom, tag, color) => {
restoreByTag(plot, zoom, tag, color)
}
// ---------------------------------- 图例渲染,在这保存数据,传给legend组件 ----------------------------------
const legend = ref(null)
const legendHoverin = (item, zoom) => {
// console.log('mouseenter', item)
const plot = zoom ? zoomChartObj : chartObj
thickenByTag(plot, zoom, item.name, item.color)
}
const legendHoverout = (item, zoom) => {
// console.log('mouseleave', item)
const plot = zoom ? zoomChartObj : chartObj
restoreByTag(plot, zoom, item.name, item.color)
}
// ---------------------------------- 暴露api ----------------------------------
defineExpose({
render,
Expand All @@ -639,72 +659,4 @@ defineExpose({
})
</script>
<style lang="scss">
.lc-tooltip {
@apply py-2 px-3 absolute bg-default border rounded;
box-shadow: rgba(21, 24, 31, 0.16) 0px 12px 24px 0px;
visibility: visible;
p {
@apply text-xs text-default font-semibold;
}
.lc-tooltip-item-no-zoom,
.lc-tooltip-item-zoom {
@apply flex items-center gap-3;
&:not(:last-child) {
@apply mb-1.5;
}
.lc-tooltip-color {
@apply w-5 flex items-center;
}
.lc-tooltip-color-rect {
&::before {
content: '';
display: inline-block;
width: 20px;
height: 6px;
border-radius: 2px;
margin-right: 5px;
background-color: currentColor;
}
}
}
.lc-tooltip-tip {
@apply font-normal text-dimmest text-xs;
}
}
.lc-tooltip-item-no-zoom {
.lc-tooltip-step {
@apply font-semibold;
&::after {
content: ':';
@apply font-semibold;
}
}
.lc-tooltip-value {
@apply w-10 text-left font-semibold;
}
.lc-tooltip-tag {
@apply truncate;
max-width: 128px;
}
}
.lc-tooltip-item-zoom {
.lc-tooltip-step {
@apply w-7;
}
.lc-tooltip-value {
@apply col-span-1;
@apply w-10 text-left;
}
.lc-tooltip-time {
@apply w-28;
}
.lc-tooltip-tag {
@apply truncate;
max-width: 160px;
}
}
</style>
<style lang="scss"></style>

0 comments on commit 113d4bc

Please sign in to comment.