{T}

ECharts 样式与主题

本文档介绍 ECharts 中的样式设置方式,包括颜色主题、调色盘和直接样式设置。

颜色主题(Theme)

最简单的更改全局样式的方式是直接采用颜色主题(theme)。

内置主题

ECharts 5 除了一贯的默认主题外,还内置了 'dark' 主题:

javascript
var chart = echarts.init(dom, 'dark')

自定义主题

可以在 主题编辑器 中编辑和下载主题。

JSON 格式主题

如果主题保存为 JSON 文件,需要加载和注册:

javascript
fetch('theme/vintage.json')
  .then((r) => r.json())
  .then((theme) => {
    echarts.registerTheme('vintage', theme)
    var chart = echarts.init(dom, 'vintage')
  })

UMD 格式主题

如果保存为 UMD 格式的 JS 文件,文件内部已经做了自注册,直接引入 JS 即可:

javascript
// HTML 引入 vintage.js 文件后
var chart = echarts.init(dom, 'vintage')

注册主题 API

javascript
echarts.registerTheme(themeName, themeConfig)

调色盘

调色盘给定了一组颜色,图形、系列会自动从其中选择颜色。可以设置全局的调色盘,也可以设置系列自己专属的调色盘。

全局调色盘

javascript
option = {
  color: [
    '#c23531',
    '#2f4554',
    '#61a0a8',
    '#d48265',
    '#91c7ae',
    '#749f83',
    '#ca8622',
    '#bda29a',
    '#6e7074',
    '#546570',
    '#c4ccd3'
  ],
  series: [
    // ...
  ]
}

系列调色盘

javascript
option = {
  series: [
    {
      type: 'bar',
      color: [
        '#dd6b66',
        '#759aa0',
        '#e69d87',
        '#8dc1a9',
        '#ea7e53'
      ]
    },
    {
      type: 'pie',
      color: [
        '#37A2DA',
        '#32C5E9',
        '#67E0E3',
        '#9FE6B8',
        '#FFDB5C'
      ]
    }
  ]
}

直接样式设置

直接的样式设置是比较常用的设置方式。在 ECharts 的 option 中,很多地方可以设置 itemStylelineStyleareaStylelabel 等。

itemStyle

用于设置图形元素的样式:

javascript
option = {
  series: [
    {
      type: 'bar',
      data: [10, 22, 28, 43, 49],
      itemStyle: {
        color: '#5470c6',
        borderColor: '#91cc75',
        borderWidth: 2,
        borderRadius: 5,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        shadowBlur: 10
      }
    }
  ]
}

lineStyle

用于设置线条样式:

javascript
option = {
  series: [
    {
      type: 'line',
      data: [10, 22, 28, 23, 19],
      lineStyle: {
        color: 'green',
        width: 4,
        type: 'dashed'
      }
    }
  ]
}

areaStyle

用于设置区域填充样式:

javascript
option = {
  series: [
    {
      type: 'line',
      data: [10, 22, 28, 23, 19],
      areaStyle: {
        color: 'rgba(84, 112, 198, 0.5)'
      }
    }
  ]
}

label

用于设置标签样式:

javascript
option = {
  series: [
    {
      type: 'bar',
      data: [10, 22, 28, 43, 49],
      label: {
        show: true,
        position: 'top',
        color: '#333',
        fontSize: 14,
        fontWeight: 'bold'
      }
    }
  ]
}

高亮样式

通过 emphasis 设置鼠标悬停时的高亮样式:

javascript
option = {
  series: [
    {
      type: 'bar',
      data: [10, 22, 28, 43, 49],
      emphasis: {
        itemStyle: {
          color: '#91cc75',
          shadowBlur: 10,
          shadowColor: 'rgba(0, 0, 0, 0.5)'
        },
        label: {
          show: true,
          fontSize: 16
        }
      }
    }
  ]
}

渐变色

ECharts 支持线性渐变和径向渐变。

线性渐变

javascript
option = {
  series: [
    {
      type: 'bar',
      data: [10, 22, 28, 43, 49],
      itemStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            { offset: 0, color: '#83bff6' },
            { offset: 0.5, color: '#188df0' },
            { offset: 1, color: '#188df0' }
          ]
        }
      }
    }
  ]
}

径向渐变

javascript
option = {
  backgroundColor: {
    type: 'radial',
    x: 0.3,
    y: 0.3,
    r: 0.8,
    colorStops: [
      { offset: 0, color: '#f7f8fa' },
      { offset: 1, color: '#cdd0d5' }
    ]
  }
}

纹理填充

可以使用图片作为纹理填充:

javascript
option = {
  series: [
    {
      type: 'bar',
      data: [10, 22, 28, 43, 49],
      itemStyle: {
        color: {
          image: 'path/to/image.png',
          repeat: 'repeat'
        }
      }
    }
  ]
}

文本样式

基本文本样式

javascript
option = {
  title: {
    text: '标题文本',
    textStyle: {
      color: '#333',
      fontStyle: 'normal',
      fontWeight: 'bold',
      fontFamily: 'Arial',
      fontSize: 18
    }
  }
}

文本描边

javascript
option = {
  series: [
    {
      type: 'line',
      data: [10, 22, 28, 23, 19],
      label: {
        show: true,
        textBorderColor: '#000',
        textBorderWidth: 2
      }
    }
  ]
}

文本阴影

javascript
option = {
  series: [
    {
      type: 'line',
      data: [10, 22, 28, 23, 19],
      label: {
        show: true,
        textShadowColor: 'rgba(0, 0, 0, 0.5)',
        textShadowBlur: 5,
        textShadowOffsetX: 2,
        textShadowOffsetY: 2
      }
    }
  ]
}

坐标轴样式

坐标轴线样式

javascript
option = {
  xAxis: {
    axisLine: {
      lineStyle: {
        color: '#333',
        width: 2
      }
    }
  },
  yAxis: {
    axisLine: {
      lineStyle: {
        color: '#333',
        width: 2
      }
    }
  }
}

分隔线样式

javascript
option = {
  xAxis: {
    splitLine: {
      lineStyle: {
        color: '#ddd',
        type: 'dashed'
      }
    }
  },
  yAxis: {
    splitLine: {
      lineStyle: {
        color: '#ddd',
        type: 'dashed'
      }
    }
  }
}

刻度样式

javascript
option = {
  xAxis: {
    axisTick: {
      lineStyle: {
        color: '#333'
      }
    },
    axisLabel: {
      color: '#666',
      fontSize: 12
    }
  }
}

提示框样式

javascript
option = {
  tooltip: {
    backgroundColor: 'rgba(50, 50, 50, 0.7)',
    borderColor: '#333',
    borderWidth: 1,
    padding: 10,
    textStyle: {
      color: '#fff',
      fontSize: 14
    }
  }
}

图例样式

javascript
option = {
  legend: {
    backgroundColor: '#f5f5f5',
    borderColor: '#ddd',
    borderWidth: 1,
    borderRadius: 5,
    padding: 10,
    textStyle: {
      color: '#333',
      fontSize: 14
    }
  }
}

深色模式适配

使用内置深色主题

javascript
var chart = echarts.init(dom, 'dark')

自定义深色模式

javascript
option = {
  backgroundColor: '#1a1a1a',
  title: {
    textStyle: {
      color: '#fff'
    }
  },
  legend: {
    textStyle: {
      color: '#ccc'
    }
  },
  xAxis: {
    axisLine: {
      lineStyle: {
        color: '#ccc'
      }
    },
    axisLabel: {
      color: '#ccc'
    }
  },
  yAxis: {
    axisLine: {
      lineStyle: {
        color: '#ccc'
      }
    },
    axisLabel: {
      color: '#ccc'
    }
  }
}

动态主题切换

javascript
function toggleTheme(isDark) {
  // 销毁当前实例
  chart.dispose()

  // 使用新主题重新初始化
  chart = echarts.init(dom, isDark ? 'dark' : null)
  chart.setOption(option)
}

响应式布局

ECharts 图表可以自适应容器大小,实现响应式布局。

基础响应式

javascript
const chart = echarts.init(dom)

// 监听窗口大小变化
window.addEventListener('resize', () => {
  chart.resize()
})

使用 ResizeObserver

推荐使用 ResizeObserver 实现更精确的监听:

javascript
const chart = echarts.init(dom)
const observer = new ResizeObserver(() => {
  chart.resize()
})

observer.observe(dom)

// 销毁时断开监听
// observer.disconnect()

媒体查询适配

根据屏幕尺寸调整图表配置:

javascript
function getResponsiveOption() {
  const width = window.innerWidth
  const isMobile = width < 768

  return {
    grid: {
      left: isMobile ? '3%' : '5%',
      right: isMobile ? '3%' : '5%',
      bottom: isMobile ? '15%' : '10%',
      top: isMobile ? '15%' : '10%'
    },
    legend: {
      orient: isMobile ? 'horizontal' : 'vertical',
      top: isMobile ? 'top' : 'middle',
      right: isMobile ? 'center' : 'right'
    },
    title: {
      textStyle: {
        fontSize: isMobile ? 14 : 18
      }
    },
    xAxis: {
      axisLabel: {
        rotate: isMobile ? 45 : 0,
        fontSize: isMobile ? 10 : 12
      }
    }
  }
}

// 初始化
const chart = echarts.init(dom)
chart.setOption({
  ...baseOption,
  ...getResponsiveOption()
})

// 窗口变化时重新计算
window.addEventListener('resize', () => {
  chart.setOption(getResponsiveOption())
  chart.resize()
})

移动端适配

javascript
option = {
  // 移动端触摸交互
  toolbox: {
    show: true,
    orient: 'vertical',
    right: 10,
    top: 'center'
  },

  // 移动端字体适配
  title: {
    textStyle: {
      fontSize: window.innerWidth < 768 ? 14 : 18
    }
  },

  // 移动端间距适配
  grid: {
    left: '3%',
    right: '3%',
    bottom: '10%',
    top: '10%',
    containLabel: true
  },

  // 移动端标签适配
  series: [{
    label: {
      fontSize: window.innerWidth < 768 ? 10 : 12
    }
  }]
}

自适应文字大小

javascript
function getAdaptiveFontSize(baseSize) {
  const width = window.innerWidth
  const scale = Math.min(width / 1920, 1)  // 最大 1
  return Math.max(baseSize * scale, 10)  // 最小 10px
}

option = {
  title: {
    textStyle: {
      fontSize: getAdaptiveFontSize(18)
    }
  },
  xAxis: {
    axisLabel: {
      fontSize: getAdaptiveFontSize(12)
    }
  }
}

容器百分比布局

html
<style>
  .chart-container {
    width: 100%;
    height: 50vh;  /* 视口高度的 50% */
    min-height: 300px;
  }
</style>

<div class="chart-container" id="chart"></div>

<script>
  const chart = echarts.init(document.getElementById('chart'))

  // 初始调整大小
  chart.resize()

  // 监听窗口变化
  window.addEventListener('resize', () => chart.resize())
</script>

响应式网格布局

多个图表的响应式布局:

html
<style>
  .charts-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
    gap: 20px;
  }
  .chart-item {
    height: 300px;
  }
</style>

<div class="charts-grid">
  <div class="chart-item" id="chart1"></div>
  <div class="chart-item" id="chart2"></div>
  <div class="chart-item" id="chart3"></div>
</div>

<script>
  const charts = []

  document.querySelectorAll('.chart-item').forEach(dom => {
    const chart = echarts.init(dom)
    chart.setOption(getOption())
    charts.push(chart)
  })

  // 使用 ResizeObserver 监听所有图表
  const observer = new ResizeObserver(() => {
    charts.forEach(chart => chart.resize())
  })

  document.querySelectorAll('.chart-item').forEach(dom => {
    observer.observe(dom)
  })
</script>

相关链接