双 11、618 是近些年来兴起的购物节,每到这个时候商品的销售数量和销售额都非常巨大。如此庞大的数据通过表格的形式很难观察其增减趋势,图表能更加直观的显示数据的变化。目前,云课后台已经实时统计了 1 小时平台课程的销售数量和销售额,本题需要使用
echarts
将这些数据用图表的方式显示到前端。
开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:
├── effect.gif
├── css
│ └── index.css
├── index.html
└── js
├── echarts.js
└── index.js
其中:
index.html
是主页面。index.js
是待完善的 js 文件。echarts.js
是 echarts 文件。index.css
是 css 样式文件。effect.gif
是完成的效果图。注意:打开环境后发现缺少项目代码,请复制下述命令至命令行进行下载。
cd /home/project
wget -q https://labfile.oss.aliyuncs.com/courses/18164/test2.zip
unzip test2.zip && rm test2.zip
在浏览器中预览 index.html
页面,显示如下所示:
请在
js/index.js
文件中补全代码。 最终效果可参考文件夹下面的 gif 图,图片名称为effect.gif
(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。
具体需求如下:
yAxis
的设置,要求“销售额”(即,配置项 name
)的位置(即,配置项 position
)在图表的左侧,“销量”(即,配置项 name
)的位置(即,配置项 position
)在图表的右侧。renderChart
函数中的代码,正确给 X 轴的时间,以及 Y 轴的销售额和销量赋值。js/index.js
文件外的任何内容。// 指定图表的配置项和数据
const charData = {
title: {
text: '云课课程销量和销售额看板',
width: 100,
height: 50,
textStyle: {
lineHeight: 50,
},
left: 'center',
},
grid: {
top: 80,
},
tooltip:{
show: true,
},
xAxis: {
data: [],
},
// TODO:补全 `yAxis` 的设置,要求“销售额”(即,配置项 `name`)的位置(即,配置项 `position`)在图表的左侧,“销量”(即,配置项 `name`)的位置(即,配置项 `position`)在图表的右侧。
yAxis: [{
type: 'value',
name: '销售额',
position: 'left',
},
{
type: 'value',
name: '销量',
position: 'right',
}],
series: [
{
name: '销售额',
type: 'line',
data: [],
yAxisIndex: 0,
smooth: true
},
{
name: '销量',
type: 'bar',
data: [],
yAxisIndex: 1,
smooth: true
}
]
};
// 以下代码为模拟后端服务器返回数据
let sale = 0;
let count = 0;
// 销售额
const saleObj = {};
// 销量
const countObj = {};
let index = 0;
function Ajax() {
return new Promise((resolve, reject) => {
let randomNum = Math.random();
const randomSum = () => (randomNum * 500 + 900);
const randomCount = () => (randomNum * 50 + 80);
let i = index++ * 10
let key = `10:${i == 0 ? "00" : i}`;
if (index < 7) {
sale = randomSum();
Object.assign(saleObj, { [key]: sale.toFixed(2) })
count = randomCount();
Object.assign(countObj, { [key]: count.toFixed(2) })
}
const respondBody = {
"code": 200,
"msg": "success",
"data": {
saleObj,
countObj
}
};
setTimeout(() => {
resolve(respondBody);
}, 1000)
})
}
async function renderChart() {
const result = await Ajax();
document.querySelector("#result").innerText = JSON.stringify(result);
const myChart = echarts.init(document.getElementById('main'));
// TODO:补全代码,正确给 X 轴的时间,以及 Y 轴的商品的销售额 saleObj 和销量赋值 countObj。
const{saleObj,countObj}=result.data;
charData.xAxis.data = Object.keys(saleObj);
charData.series[0].data= Object.values(saleObj).map(Number);
charData.series[1].data= Object.values(countObj).map(Number);
myChart.setOption(charData, true);
document.querySelector("#data").innerText = JSON.stringify(charData);
}
renderChart();
let times = 0;
let timer = setInterval(() => {
renderChart();
++times == 6 && clearInterval(timer);
}, 2000)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>展品销量和销售额实时展示看板</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="container">
<div id="main" style="width: 600px;height:400px;"></div>
</div>
<div id="result" class="hide"></div>
<div id="data" class="hide"></div>
<script src="./js/echarts.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
<!DOCTYPE html>
:声明文档类型为 HTML5,告知浏览器按照 HTML5 的标准来解析页面。<html lang="zh-CN">
:根标签,lang="zh-CN"
表示页面使用中文(中国大陆地区)语言。<head>
部分: <meta charset="UTF-8">
:设置页面字符编码为 UTF - 8,确保页面能正确显示各种字符。<meta http-equiv="X-UA-Compatible" content="IE=edge">
:指定页面在 Internet Explorer 浏览器中以最新的渲染模式显示。<meta name="viewport" content="width=device-width, initial-scale=1.0">
:用于适配移动端,使页面在不同设备上能正确显示。<title>
:设置页面的标题,显示在浏览器的标签页上。<link rel="stylesheet" href="./css/index.css">
:引入外部 CSS 文件 index.css
,用于设置页面的样式。<body>
部分: <div class="container">
:一个容器元素,用于包裹内部的图表容器,方便进行样式设置。<div id="main" style="width: 600px;height:400px;"></div>
:用于承载 ECharts 图表的容器,设置了固定的宽度和高度。<div id="result" class="hide"></div>
和 <div id="data" class="hide"></div>
:用于显示服务器返回的数据和图表配置数据,class="hide"
使其初始状态下隐藏。<script src="./js/echarts.js"></script>
和 <script src="./js/index.js"></script>
:分别引入 ECharts 库和自定义的 JavaScript 代码。* {
margin: 0;
padding: 0;
}
.container {
width: 600px;
margin: 0 auto;
margin-top: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
border-radius: 15px;
}
.hide {
display: none;
}
* { margin: 0; padding: 0; }
:全局选择器,将所有元素的外边距和内边距都设置为 0,消除浏览器的默认样式。.container
:对具有 container
类名的元素进行样式设置。 width: 600px;
:设置容器宽度为 600 像素。margin: 0 auto;
:使容器在水平方向上居中显示。margin-top: 20px;
:设置容器距离顶部 20 像素的外边距。box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
:为容器添加阴影效果,增加立体感。border-radius: 15px;
:设置容器的边框圆角为 15 像素,使容器的边角更圆润。.hide
:对具有 hide
类名的元素进行样式设置,display: none;
使其隐藏。1. 图表配置对象 charData
const charData = {
title: {
text: '云课课程销量和销售额看板',
width: 100,
height: 50,
textStyle: {
lineHeight: 50,
},
left: 'center',
},
grid: {
top: 80,
},
tooltip: {
show: true,
},
xAxis: {
data: [],
},
yAxis: [{
type: 'value',
name: '销售额',
position: 'left',
},
{
type: 'value',
name: '销量',
position: 'right',
}],
series: [
{
name: '销售额',
type: 'line',
data: [],
yAxisIndex: 0,
smooth: true
},
{
name: '销量',
type: 'bar',
data: [],
yAxisIndex: 1,
smooth: true
}
]
};
title
:用于设置图表的标题。text
是标题的文本内容;width
和 height
分别设置标题的宽度和高度;textStyle
中的 lineHeight
用于设置标题文本的行高;left: 'center'
表示将标题水平居中显示。grid
:设置图表网格的布局。top: 80
表示网格距离容器顶部 80 个像素。tooltip
:设置鼠标悬停在图表上时的提示框。show: true
表示显示提示框。xAxis
:配置 X 轴。data
是一个空数组,后续会将时间数据填充进去。yAxis
:配置 Y 轴,使用了双 Y 轴。第一个 yAxis
对象的 name
为 '销售额'
,position
为 'left'
,表示销售额在图表左侧显示;第二个 yAxis
对象的 name
为 '销量'
,position
为 'right'
,表示销量在图表右侧显示。series
:配置图表的数据系列。包含两个系列,一个是 '销售额'
的折线图(type: 'line'
),另一个是 '销量'
的柱状图(type: 'bar'
)。yAxisIndex
用于指定该系列使用哪个 Y 轴,smooth: true
表示折线图使用平滑曲线。2. 模拟后端服务器返回数据的相关代码
let sale = 0;
let count = 0;
const saleObj = {};
const countObj = {};
let index = 0;
function Ajax() {
return new Promise((resolve, reject) => {
let randomNum = Math.random();
const randomSum = () => (randomNum * 500 + 900);
const randomCount = () => (randomNum * 50 + 80);
let i = index++ * 10
let key = `10:${i == 0 ? "00" : i}`;
if (index < 7) {
sale = randomSum();
Object.assign(saleObj, { [key]: sale.toFixed(2) })
count = randomCount();
Object.assign(countObj, { [key]: count.toFixed(2) })
}
const respondBody = {
"code": 200,
"msg": "success",
"data": {
saleObj,
countObj
}
};
setTimeout(() => {
resolve(respondBody);
}, 1000)
})
}
sale
和 count
分别用于临时存储每次生成的销售额和销量。saleObj
和 countObj
是对象,用于存储不同时间点的销售额和销量数据。index
是一个计数器,用于生成不同的时间点。Ajax
函数: Promise
对象,模拟异步请求。randomNum
,并定义两个函数 randomSum
和 randomCount
分别用于生成随机的销售额和销量。index
生成时间字符串 key
,格式为 '10:XX'
。index
小于 7 时,生成随机的销售额和销量,并将其添加到 saleObj
和 countObj
中。respondBody
,包含状态码、消息和数据。setTimeout
模拟 1 秒的延迟,然后将响应对象传递给 resolve
函数。3. 渲染图表的函数 renderChart
async function renderChart() {
const result = await Ajax();
document.querySelector("#result").innerText = JSON.stringify(result);
const myChart = echarts.init(document.getElementById('main'));
const { saleObj, countObj } = result.data;
charData.xAxis.data = Object.keys(saleObj);
charData.series[0].data = Object.values(saleObj).map(Number);
charData.series[1].data = Object.values(countObj).map(Number);
myChart.setOption(charData, true);
document.querySelector("#data").innerText = JSON.stringify(charData);
}
await
关键字等待 Ajax
函数返回结果,并将结果存储在 result
变量中。id
为 result
的元素中。echarts.init
方法初始化一个 ECharts 实例,绑定到 id
为 main
的元素上。result.data
中解构出 saleObj
和 countObj
。将 saleObj
的键(时间)赋值给 charData.xAxis.data
,作为 X 轴的数据;将 saleObj
的值转换为数字后赋值给 charData.series[0].data
,作为销售额的数据;将 countObj
的值转换为数字后赋值给 charData.series[1].data
,作为销量的数据。myChart.setOption
方法将配置对象 charData
应用到图表上,true
表示不合并配置,直接覆盖。charData
转换为 JSON 字符串,并显示在 id
为 data
的元素中。4. 定时调用 renderChart
函数
renderChart();
let times = 0;
let timer = setInterval(() => {
renderChart();
++times == 6 && clearInterval(timer);
}, 2000)
renderChart
函数来初始化图表。times
和一个定时器 timer
,使用 setInterval
每隔 2 秒调用一次 renderChart
函数。times
加 1,当 times
等于 6 时,使用 clearInterval
清除定时器,停止定时调用。四、工作流程▶️
js/index.js
中的代码,定义图表配置对象 charData
和模拟数据的 Ajax
函数。renderChart
函数,该函数内部调用 Ajax
函数获取模拟的销售额和销量数据。将获取到的数据更新到 charData
中,然后使用 ECharts 初始化图表并应用配置,将图表显示在 id
为 main
的容器中。同时,将服务器返回的数据和更新后的图表配置数据分别显示在 id
为 result
和 data
的元素中。setInterval
每隔 2 秒调用一次 renderChart
函数,重复步骤 3 的操作,实现图表数据的实时更新。当调用次数达到 6 次时,停止定时调用。通过以上流程,实现了商品销量和销售额实时展示看板的效果。