效果图
目录
项目介绍
本项目将用 Vue 和 ECharts 实现一个统计分析页面,包含三个可切换的选项卡,每个选项卡下方展示不同的图表内容(柱状图、饼图、折线图)。我们会详细讲解从 HTML 结构、样式设计到 Vue 和 ECharts 的集成过程。
开发环境设置
首先,确保你已安装基础的前端开发环境,并了解 Vue 和 JavaScript 的基础知识。
-
新建一个 HTML 文件(如
index.html
)。 -
引入 Vue.js 和 ECharts 的 CDN 文件:
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script> <script src="https://cdn.staticfile.net/echarts/5.0.0/echarts.min.js"></script>
代码实现
HTML 和 CSS 部分
HTML 和 CSS 负责页面的基本结构和样式设置。我们首先定义了一个应用的挂载点 #app
,并分割了几个功能区域:头部、用户信息、选项卡、问题展示和图表区域。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>统计分析页面 - Vue 示例</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
#app {
max-width: 400px;
margin: 20px auto;
padding: 10px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
font-size: 18px;
font-weight: bold;
color: #333;
border-bottom: 1px solid #ddd;
}
.info {
padding: 10px;
display: flex;
align-items: center;
}
.info img {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #ddd;
margin-right: 10px;
}
.tabs {
display: flex;
justify-content: space-around;
margin: 10px 0;
}
.tab {
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
color: #666;
font-size: 14px;
}
.tab.active {
background-color: #2c5cac;
color: #fff;
}
.question-section {
padding: 10px;
border-top: 1px solid #ddd;
}
.question-title {
font-size: 16px;
margin: 10px 0;
}
.chart {
width: 100%;
height: 250px;
}
</style>
</head>
Vue 逻辑和数据
在 Vue
中,我们使用 activeTab
来记录当前选项卡状态,以便动态切换内容。setActiveTab
方法则用于切换选项卡,同时更新图表数据。
<script>
new Vue({
el: '#app',
data: {
activeTab: 'dataStats', // 当前激活的选项卡
chartInstance: null // 存储 ECharts 图表实例
},
mounted() {
this.initChart(); // 初始化图表
},
methods: {
// 设置当前选项卡
setActiveTab(tab) {
this.activeTab = tab;
this.updateChart(); // 更新图表数据
},
// 初始化图表
initChart() {
this.chartInstance = echarts.init(this.$refs.chart);
this.updateChart(); // 首次加载数据
},
ECharts 图表初始化与更新
根据不同的 activeTab
值,我们展示不同的图表:柱状图、饼图和折线图。updateChart
方法包含了三个图表的配置:
updateChart() {
let chartOptions = {
};
if (this.activeTab === 'dataStats') {
// 数据统计的柱状图
chartOptions = {
color: ['#6a0dad', '#1e90ff', '#00ced1', '#ff6347', '#3cb371'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow' }
},
xAxis: {
type: 'category',
data: ['研发工程师', '数据师', '设计师', '运营同学', '产品经理'],
axisLabel: {
fontSize: 12 }
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: 12 }
},
series: [
{
name: '人数',
type: 'bar',
data: [39, 14, 35, 5, 18],
barWidth: '50%'
}
]
};
} else if (this.activeTab === 'sourceAnalysis') {
// 来源分析的饼图
chartOptions = {
color: ['#ffcc66', '#66c2ff', '#ff9966', '#66ff99'],
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
series: [
{
name: '来源分析',
type: 'pie',
radius: '70%',
data: [
{
value: 60, name: '在线渠道' },
{
value: 20, name: '线下活动' },
{
value: 15, name: '朋友推荐' },
{
value: 7, name: '其他' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
} else if (this.activeTab === 'crossAnalysis') {
// 交叉分析的折线图
chartOptions = {
color: ['#2c5cac'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line' }
},
xAxis: {
type: 'category',
data: ['一月', '二月', '三月', '四月', '五月'],
axisLabel: {
fontSize: 12 }
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: 12 }
},
series: [
{
name: '调研数据',
type: 'line',
data: [10, 20, 15, 30, 25]
}
]
};
}
this.chartInstance.setOption(chartOptions);
}
}
});
</script>
效果展示
- 切换到 数据统计 时,会展示柱状图。
- 切换到 来源分析 时,会展示饼图。
- 切换到 交叉分析 时,会展示折线图。
总结
通过此项目,我们学习了如何使用 Vue 和 ECharts 集成,实现一个带有动态数据切换功能的统计分析页面。此类页面广泛应用于问卷分析、数据展示等场景,为前端开发新手提供了实战机会。
希望这篇教程能帮助你更好地理解 Vue 和 ECharts 的结合使用!
完整代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>统计分析页面 - Vue 示例</title>
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
<script src="https://cdn.staticfile.net/echarts/5.0.0/echarts.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
#app {
max-width: 400px;
margin: 20px auto;
padding: 10px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
font-size: 18px;
font-weight: bold;
color: #333;
border-bottom: 1px solid #ddd;
}
.info {
padding: 10px;
display: flex;
align-items: center;
}
.info img {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #ddd;
margin-right: 10px;
}
.tabs {
display: flex;
justify-content: space-around;
margin: 10px 0;
}
.tab {
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
color: #666;
font-size: 14px;
}
.tab.active {
background-color: #2c5cac;
color: #fff;
}
.question-section {
padding: 10px;
border-top: 1px solid #ddd;
}
.question-title {
font-size: 16px;
margin: 10px 0;
}
.chart {
width: 100%;
height: 250px;
}
</style>
</head>
<body>
<div id="app">
<!-- Header Section -->
<div class="header">
<div>统计分析</div>
<div style="font-size: 22px;">•••</div>
</div>
<!-- Info Section -->
<div class="info">
<img alt="用户头像" />
<div>调研人数 132</div>
</div>
<!-- Title Section -->
<div style="text-align: center; padding: 10px;">
<div style="font-weight: bold;">问卷调查结果</div>
<div style="color: #888;">2017.12.08 - 2018.03.22</div>
</div>
<!-- Tabs -->
<div class="tabs">
<div class="tab" :class="{ active: activeTab === 'dataStats' }" @click="setActiveTab('dataStats')">数据统计</div>
<div class="tab" :class="{ active: activeTab === 'sourceAnalysis' }" @click="setActiveTab('sourceAnalysis')">来源分析</div>
<div class="tab" :class="{ active: activeTab === 'crossAnalysis' }" @click="setActiveTab('crossAnalysis')">交叉分析</div>
</div>
<!-- Question Section -->
<div class="question-section">
<div class="question-title" v-if="activeTab === 'dataStats'">01 [单选题] 您的岗位是?</div>
<div class="question-title" v-if="activeTab === 'sourceAnalysis'">02 [单选题] 您是从哪里知道我们这个岗位的?</div>
<div class="question-title" v-if="activeTab === 'crossAnalysis'">03 [单选题] 您的入职时间是几月份?</div>
<div class="chart" ref="chart"></div>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
activeTab: 'dataStats', // 当前激活的选项卡
chartInstance: null // 存储 ECharts 图表实例
},
mounted() {
this.initChart(); // 初始化图表
},
methods: {
// 设置当前选项卡
setActiveTab(tab) {
this.activeTab = tab;
this.updateChart(); // 更新图表数据
},
// 初始化图表
initChart() {
this.chartInstance = echarts.init(this.$refs.chart);
this.updateChart(); // 首次加载数据
},
// 更新图表数据
updateChart() {
let chartOptions = {
};
if (this.activeTab === 'dataStats') {
// 数据统计的柱状图
chartOptions = {
color: ['#6a0dad', '#1e90ff', '#00ced1', '#ff6347', '#3cb371'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow' }
},
xAxis: {
type: 'category',
data: ['研发工程师', '数据师', '设计师', '运营同学', '产品经理'],
axisLabel: {
fontSize: 12 }
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: 12 }
},
series: [
{
name: '人数',
type: 'bar',
data: [39, 14, 35, 5, 18],
barWidth: '50%'
}
]
};
} else if (this.activeTab === 'sourceAnalysis') {
// 来源分析的饼图
chartOptions = {
color: ['#ffcc66', '#66c2ff', '#ff9966', '#66ff99'],
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
series: [
{
name: '来源分析',
type: 'pie',
radius: '70%',
data: [
{
value: 60, name: '在线渠道' },
{
value: 20, name: '线下活动' },
{
value: 15, name: '朋友推荐' },
{
value: 7, name: '其他' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
} else if (this.activeTab === 'crossAnalysis') {
// 交叉分析的折线图
chartOptions = {
color: ['#2c5cac'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line' }
},
xAxis: {
type: 'category',
data: ['一月', '二月', '三月', '四月', '五月'],
axisLabel: {
fontSize: 12 }
},
yAxis: {
type: 'value',
axisLabel: {
fontSize: 12 }
},
series: [
{
name: '调研数据',
type: 'line',
data: [10, 20, 15, 30, 25]
}
]
};
}
// 设置图表的选项
this.chartInstance.setOption(chartOptions);
}
}
});
</script>
</body>
</html>