You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dash Python中实现卡片展开及图表自动调整大小

Dashboard卡片展开/收起+图表自适应实现方案

下面是几种主流技术栈的可行实现方案,覆盖原生前端及常用框架,核心是通过状态切换控制卡片展开/收起,同时触发图表重绘实现尺寸自适应:

原生HTML/CSS/JS实现

适合无框架的轻量Dashboard,用CSS过渡实现平滑动画,JS处理交互逻辑:

<!-- 卡片结构 -->
<div class="dashboard-card">
  <div class="card-header">
    <h3>用户活跃度统计</h3>
    <button class="toggle-btn">▼</button>
  </div>
  <div class="card-content">
    <div class="chart-container" id="activityChart"></div>
  </div>
</div>
/* 基础样式与过渡动画 */
.dashboard-card {
  border: 1px solid #eee;
  border-radius: 8px;
  margin: 16px 0;
  overflow: hidden;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #f8f9fa;
  cursor: pointer;
}

.toggle-btn {
  border: none;
  background: transparent;
  font-size: 18px;
  transition: transform 0.3s;
}

.card-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
  padding: 0 16px;
}

/* 展开状态样式 */
.card-content.expanded {
  max-height: 600px; /* 根据图表高度调整最大值 */
  padding: 16px;
}

.toggle-btn.expanded {
  transform: rotate(180deg);
}

.chart-container {
  width: 100%;
  height: 300px;
}
// 交互逻辑与图表自适应
document.querySelectorAll('.toggle-btn').forEach(btn => {
  btn.addEventListener('click', function() {
    const card = this.closest('.dashboard-card');
    const content = card.querySelector('.card-content');
    
    // 切换展开/收起状态
    content.classList.toggle('expanded');
    this.classList.toggle('expanded');
    
    // 触发图表重绘(以ECharts为例)
    const chart = echarts.getInstanceByDom(content.querySelector('.chart-container'));
    if (chart) {
      // 延迟300ms确保过渡完成后再resize
      setTimeout(() => chart.resize(), 300);
    }
    // 其他图表库示例:
    // Highcharts: Highcharts.charts.forEach(c => c.resize());
    // Chart.js: chartInstance.resize();
  });
});

React组件实现

适合React技术栈的Dashboard,用状态管理控制展开逻辑:

import { useState, useEffect, useRef } from 'react';
import * as echarts from 'echarts';

const DashboardCard = ({ title, chartOption }) => {
  const [isExpanded, setIsExpanded] = useState(false);
  const chartRef = useRef(null);
  let chartInstance = null;

  // 初始化图表
  useEffect(() => {
    if (chartRef.current) {
      chartInstance = echarts.init(chartRef.current);
      chartInstance.setOption(chartOption);
    }

    // 监听窗口resize
    const handleResize = () => chartInstance?.resize();
    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
      chartInstance?.dispose();
    };
  }, [chartOption]);

  // 展开时触发图表resize
  useEffect(() => {
    if (isExpanded) {
      setTimeout(() => chartInstance?.resize(), 300);
    }
  }, [isExpanded]);

  return (
    <div className="dashboard-card">
      <div className="card-header">
        <h3>{title}</h3>
        <button 
          className={`toggle-btn ${isExpanded ? 'expanded' : ''}`}
          onClick={() => setIsExpanded(!isExpanded)}
        >
          ▼
        </button>
      </div>
      <div className={`card-content ${isExpanded ? 'expanded' : ''}`}>
        <div ref={chartRef} className="chart-container"></div>
      </div>
    </div>
  );
};

// 使用示例:<DashboardCard title="用户活跃度统计" chartOption={yourChartConfig} />

Vue组件实现

适合Vue技术栈的Dashboard,通过响应式状态控制展开:

<template>
  <div class="dashboard-card">
    <div class="card-header">
      <h3>{{ title }}</h3>
      <button 
        :class="{ 'expanded': isExpanded }"
        @click="isExpanded = !isExpanded"
        class="toggle-btn"
      >
        ▼
      </button>
    </div>
    <div 
      :class="{ 'expanded': isExpanded }"
      class="card-content"
    >
      <div ref="chartContainer" class="chart-container"></div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts';

export default {
  props: ['title', 'chartOption'],
  data() {
    return {
      isExpanded: false,
      chartInstance: null
    };
  },
  mounted() {
    this.initChart();
    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    window.removeEventListener('resize', this.handleResize);
    this.chartInstance?.dispose();
  },
  watch: {
    isExpanded(newVal) {
      if (newVal) setTimeout(() => this.chartInstance?.resize(), 300);
    },
    chartOption: {
      deep: true,
      handler() { this.chartInstance?.setOption(this.chartOption); }
    }
  },
  methods: {
    initChart() {
      this.chartInstance = echarts.init(this.$refs.chartContainer);
      this.chartInstance.setOption(this.chartOption);
    },
    handleResize() { this.chartInstance?.resize(); }
  }
};
</script>

<style scoped>
/* 复用原生方案中的CSS样式,此处省略重复代码 */
</style>

关键注意事项

  • 过渡动画优化:用max-height实现平滑过渡,避免直接使用height: auto导致的动画失效,需设置合理的最大高度值。
  • 图表resize时机:CSS过渡存在延迟,需等待动画完成后再调用图表resize方法,确保图表能获取到容器的最终尺寸。
  • 多图表兼容:所有主流图表库(ECharts、Highcharts、Chart.js等)都提供了resize方法,只需对应调用即可。

内容的提问来源于stack exchange,提问作者carluqcor98

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:56:09