Skip to content

自定义主题

让图表符合品牌风格。

快速开始

基础用法

vue
<script setup>
import { ref } from 'vue'
import { RayBar } from 'raychart'

const chartOption = ref({
  backgroundColor: '#ffffff',
  series: [{
    data: [120, 200, 150, 80],
    color: ['#42b883', '#35495e', '#41b883', '#3aa876']  // 每个柱子循环使用这些颜色
  }],
  xAxis3D: { data: ['A', 'B', 'C', 'D'] }
})
</script>

<template>
  <RayBar :option="chartOption" />
</template>

工作原理

  • series.color 是颜色数组
  • 第 1 个数据用 color[0]
  • 第 2 个数据用 color[1]
  • 第 3 个数据用 color[2]
  • 第 4 个数据用 color[3]
  • 第 5 个数据又回到 color[0](循环)

预设主题

清新绿色

javascript
const chartOption = {
  backgroundColor: '#ffffff',
  series: [{
    data: [120, 200, 150, 80],
    color: ['#42b883', '#3aa876', '#33a06f', '#2d8f65']
  }],
  xAxis3D: { data: ['A', 'B', 'C', 'D'] }
}

科技蓝色

javascript
const chartOption = {
  backgroundColor: '#f5f5f5',
  series: [{
    data: [120, 200, 150, 80],
    color: ['#2080f0', '#1870d5', '#1060ba', '#0850a0']
  }],
  xAxis3D: { data: ['A', 'B', 'C', 'D'] }
}

温暖橙色

javascript
const chartOption = {
  backgroundColor: '#ffffff',
  series: [{
    data: [120, 200, 150, 80],
    color: ['#f0a020', '#d58f1c', '#ba7e18', '#a06d14']
  }],
  xAxis3D: { data: ['A', 'B', 'C', 'D'] }
}

商务灰色

javascript
const chartOption = {
  backgroundColor: '#ffffff',
  series: [{
    data: [120, 200, 150, 80],
    color: ['#8c8c8c', '#737373', '#595959', '#404040']
  }],
  xAxis3D: { data: ['A', 'B', 'C', 'D'] }
}

材质主题

金属质感

javascript
{
  series: [{
    data: [120, 200, 150],
    color: ['#c0c0c0', '#b0b0b0', '#a0a0a0'],
    itemStyle: {
      metalness: 0.8,  // 高金属度
      roughness: 0.2   // 低粗糙度 = 光滑
    }
  }],
  xAxis3D: { data: ['A', 'B', 'C'] }
}

磨砂质感

javascript
{
  series: [{
    data: [120, 200, 150],
    color: ['#42b883', '#35495e', '#41b883'],
    itemStyle: {
      metalness: 0.2,  // 低金属度
      roughness: 0.8   // 高粗糙度 = 磨砂
    }
  }],
  xAxis3D: { data: ['A', 'B', 'C'] }
}

发光效果

javascript
{
  series: [{
    data: [120, 200, 150],
    color: ['#42b883', '#35495e', '#41b883'],
    itemStyle: {
      emissive: '#42b883',      // 发光颜色
      emissiveIntensity: 0.5    // 发光强度
    }
  }],
  xAxis3D: { data: ['A', 'B', 'C'] },
  postprocessing: {
    bloom: {
      enabled: true,
      strength: 1.5
    }
  }
}

完整配置示例

vue
<script setup>
import { ref } from 'vue'
import { RayBar } from 'raychart'

const chartOption = ref({
  // 背景色
  backgroundColor: '#f5f5f5',
  
  // 系列配置
  series: [{
    name: '销售额',
    data: [120, 200, 150, 80, 70, 110, 130],
    // 颜色数组(每个柱子循环使用)
    color: ['#42b883', '#35495e', '#41b883', '#3aa876'],
    // 材质配置
    itemStyle: {
      metalness: 0.3,
      roughness: 0.5
    }
  }],
  
  // X 轴配置
  xAxis3D: {
    data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
    axisLabel: {
      textStyle: {
        color: '#666',
        fontSize: 12
      }
    }
  },
  
  // Y 轴配置
  yAxis3D: {
    name: '销售额 (万元)',
    axisLabel: {
      textStyle: {
        color: '#666',
        fontSize: 12
      }
    }
  }
})
</script>

<template>
  <div style="height: 500px">
    <RayBar :option="chartOption" />
  </div>
</template>

主题复用

方式 1:定义主题对象

vue
<script setup>
import { ref } from 'vue'
import { RayBar } from 'raychart'

// 定义主题
const myTheme = {
  colors: ['#42b883', '#35495e', '#41b883', '#3aa876'],
  backgroundColor: '#ffffff',
  itemStyle: {
    metalness: 0.3,
    roughness: 0.5
  }
}

// 使用主题
const chartOption = ref({
  backgroundColor: myTheme.backgroundColor,
  series: [{
    data: [120, 200, 150, 80],
    color: myTheme.colors,
    itemStyle: myTheme.itemStyle
  }],
  xAxis3D: { data: ['A', 'B', 'C', 'D'] }
})
</script>

<template>
  <RayBar :option="chartOption" />
</template>

方式 2:主题工厂函数

javascript
// themes.js
export function createChartOption(theme, data, xAxisData) {
  return {
    backgroundColor: theme.backgroundColor,
    series: [{
      data: data,
      color: theme.colors,
      itemStyle: theme.itemStyle
    }],
    xAxis3D: { data: xAxisData }
  }
}

export const greenTheme = {
  colors: ['#42b883', '#3aa876', '#33a06f', '#2d8f65'],
  backgroundColor: '#ffffff',
  itemStyle: {
    metalness: 0.3,
    roughness: 0.5
  }
}

export const blueTheme = {
  colors: ['#2080f0', '#1870d5', '#1060ba', '#0850a0'],
  backgroundColor: '#f5f5f5',
  itemStyle: {
    metalness: 0.4,
    roughness: 0.4
  }
}
vue
<script setup>
import { ref } from 'vue'
import { RayBar } from 'raychart'
import { createChartOption, greenTheme, blueTheme } from './themes'

const chartOption = ref(
  createChartOption(
    greenTheme,
    [120, 200, 150, 80],
    ['A', 'B', 'C', 'D']
  )
)
</script>

<template>
  <RayBar :option="chartOption" />
</template>

主题切换

vue
<template>
  <div>
    <div class="theme-switcher">
      <button 
        v-for="name in Object.keys(themes)" 
        :key="name"
        @click="currentTheme = name"
        :class="{ active: currentTheme === name }"
      >
        {{ name }}
      </button>
    </div>
    <div style="height: 500px; margin-top: 20px">
      <RayBar :option="chartOption" />
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { RayBar } from 'raychart'

const currentTheme = ref('green')

const themes = {
  green: {
    colors: ['#42b883', '#3aa876', '#33a06f', '#2d8f65'],
    backgroundColor: '#ffffff'
  },
  blue: {
    colors: ['#2080f0', '#1870d5', '#1060ba', '#0850a0'],
    backgroundColor: '#f5f5f5'
  },
  orange: {
    colors: ['#f0a020', '#d58f1c', '#ba7e18', '#a06d14'],
    backgroundColor: '#ffffff'
  }
}

const chartOption = computed(() => {
  const theme = themes[currentTheme.value]
  return {
    backgroundColor: theme.backgroundColor,
    series: [{
      data: [120, 200, 150, 80],
      color: theme.colors
    }],
    xAxis3D: { data: ['A', 'B', 'C', 'D'] }
  }
})
</script>

<style scoped>
.theme-switcher {
  display: flex;
  gap: 10px;
}

button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: white;
  cursor: pointer;
  transition: all 0.3s;
}

button:hover {
  background: #f5f5f5;
}

button.active {
  background: #42b883;
  color: white;
  border-color: #42b883;
}
</style>

主题最佳实践

1. 颜色对比度

确保足够对比度,便于区分:

javascript
// ✅ 好的对比度
color: ['#42b883', '#e74c3c', '#3498db', '#f39c12']

// ❌ 对比度不足(都是绿色系)
color: ['#42b883', '#3aa876', '#33a06f', '#2d8f65']

2. 无障碍设计

考虑色盲用户,避免仅依赖颜色:

javascript
// ✅ 不同亮度和饱和度
color: ['#e74c3c', '#3498db', '#2ecc71', '#f39c12']

// ❌ 红绿色盲难以区分
color: ['#e74c3c', '#2ecc71']

3. 品牌一致性

使用品牌色:

javascript
const brandTheme = {
  colors: [
    '#FF6B6B',  // 品牌主色
    '#4ECDC4',  // 品牌辅色 1
    '#45B7D1',  // 品牌辅色 2
    '#FFA07A'   // 品牌辅色 3
  ],
  backgroundColor: '#ffffff'
}

4. 颜色数量

建议提供 4-8 种颜色:

javascript
// ✅ 合适的颜色数量
color: ['#42b883', '#35495e', '#41b883', '#3aa876']

// ❌ 太少(只有 2 种)
color: ['#42b883', '#35495e']

// ❌ 太多(难以区分)
color: ['#c1', '#c2', '#c3', '#c4', '#c5', '#c6', '#c7', '#c8', '#c9', '#c10']

相关文档