很多时候web开发也会需要用到统计图,如果单纯靠我们自己那点拙劣的css和js水平设计的话,又耗时间又做得跟史一样,这时候就需要引入别人设计师为我们设计好的动态统计图——echarts
Echarts的官网是:Apache ECharts
1、第一步:引入echarts
跟引入bootstrap、Vue这些一样,你可以选择引入本地的js文件,或者用在线的CDN
本地的文件在本文顶部开头中,自己下载。如果找不到我的资源可以下载这个链接https://registry.npmjs.org/echarts/-/echarts-5.5.0.tgz,解压后找到【dist】文件夹,找到【echarts.js】文件,把它解压到你要用它的同级目录下,然后引入本地js文件到html中
<!-- 引入刚刚下载的 ECharts 文件 -->
<script src="echarts.js"></script>
或者不要那么麻烦,直接用在线CDN,我更偏向这种,把这段代码写到你的html文件里
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
2、第二步,为echarts统计图表设置一个固定宽度和高度的容器
例如:
<!-- css部分 -->
<style>
.echarts-box {width: 600px;height: 400px;padding: 30px;margin: 0 auto;border: 1px solid #ccc;}
</style><!-- HTML部分 -->
<body><!-- 为 ECharts 准备一个定义了宽高的 DOM --><div class="echarts-box" id="main"></div>
</body>
3、然后直接开始CV大法,乱用爽用
点开【示例】,会看到各种花里胡哨的图,直接选择自己喜欢的点击,样例代码都给你了,直接开始cv
但是它代码提供的只是这个样例的代码,并没有提供我们怎么去创建它并开启它的代码,要我们手动开启,也很简单:
1、echarts.init( )函数是开始创建这个样例的容器,你上面HTML已经写了一个容器了,那么现在echarts需要知道那个容器是用来存放、展示echarts图表的,你只需要用JavaScript绑定这个DOM元素然后传参给echarts.init( )函数就行了
let myChart = echarts.init(document.getElementById('main'));
2、通过【echars容器变量.setOption( )】函数显示图表
.setOption()函数需要往里传入配置数据参数,这个【配置数据参数】就是你刚刚网页上copy的那一堆代码,你可以直接copy到.setOption()里;也可以用一个变量等于你刚刚那一堆配置数据,然后再把变量放进.setOption()里
// 指定图表的配置项和数据
//这个案例是柱状图
let option = {title: {text: 'ECharts柱状图示例'},tooltip: {},legend: {data: ['销量']},xAxis: {data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
下面代码是两个完整的例子:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.echarts-box {width: 600px;height: 400px;padding: 30px;margin: 0 auto;border: 1px solid #ccc;}</style>
</head>
<body><div class="echarts-box" id="main"></div><div class="echarts-box No2" id="main"></div><script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script><script type="text/javascript">// 基于准备好的dom,初始化echarts实例let myChart = echarts.init(document.getElementById('main'));// 指定图表的配置项和数据//这个案例是柱状图let option = {title: {text: 'ECharts柱状图示例'},tooltip: {},legend: {data: ['销量']},xAxis: {data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);//这个案例是圆饼图let myChart2 = echarts.init(document.querySelector('.No2'))let option2 = {title: {text: '岑梓铭的圆饼图',subtext: '靓不靓啊?',left: 'center'},tooltip: {trigger: 'item'},legend: {orient: 'vertical',left: 'left'},series: [{name: 'Access From',type: 'pie',radius: '50%',data: [{ value: 1048, name: '吃饭' },{ value: 735, name: '睡觉' },{ value: 580, name: '玩手机' },{ value: 484, name: '学习' },{ value: 300, name: '看美女' }],emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}]};myChart2.setOption(option2)</script>
</body>
</html>
具体你需要配置什么标题、解释文字、颜色,这些你可以直接在在线示例里修改它的代码,然后慢慢找代码的哪个地方对应图表的哪个地方
具体例子还可以到这个网站去看看:echarts官网 | 中文官网
另外,在Vue中使用echart图表的话,建议刚刚那些代码写在mounted( )函数里,这样的话根据option里的配置数据(或者是绑定了data里的初始数据),当页面刚进入就能看到一个初始的图表样子。
mounted () {let myChart = echarts.init(document.querySelector('#main'))myChart.setOption({// 大标题title: {text: '消费账单列表',left: 'center'},// 提示框tooltip: {trigger: 'item'},// 图例legend: {orient: 'vertical',left: 'left'},// 数据项series: [{name: '消费账单',type: 'pie',radius: '50%', // 半径data: [{ value: 1048, name: '球鞋' },{ value: 735, name: '防晒霜' }],emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}]})
},
那么如果你要动态更新的话,只需要在Vue的methods函数配置项里设置一个函数,在这个函数里再次.setOption( )就可以了动态更新了。
但是这里有一个需要注意的:你在methods的函数里设置.setOption( ),说明你已经离开mounted函数了,那就拿不到【代表echarts图表的容器】了,那怎么setOption呢?记住一点:只要要在Vue里想全局使用某个变量,就把他挂到data里。那么这里也可以把【代表echarts图表的容器】挂到data
上面的例子改一下(数据配置啥的代码省略了,一样的):
data: {//挂载的全局变量list: [],name: '',price: ''
},
computed: {某函数 () {return 统计结果}
},
created () {//做一些网络数据请求、数据操作
},
mounted () {//直接一个【this.变量】,甚至都不用在data里设置变量,就可以到处用它了this.myChart = echarts.init(document.querySelector('#main'))this.myChart.setOption({//echarts的数据配置})
},
现在再拿【this.变量】去setOption()就可以更新图表了
methods: {// 更新图表// 现在就可以用this.myChart去调用setOption()了this.myChart.setOption({// 其他项可以不用复制过来,只用设置要修改的数据项就好了// 数据项series: [{// 这里也不是一个一个数据写好去配置,而是采用动态配置// data: [// { value: 1048, name: '球鞋' },// { value: 735, name: '防晒霜' }// ]data: this.list.map(item => ({ value: item.price, name: item.name}))//这里先解释一下.map()函数是什么意思//.map()函数是遍历数组每个成员,然后return一个经过修改的值,作为遍历到的这个成员的新值//item是自定义的,代表遍历到的数组的每一个成员//然后()=>箭头函数如果是一个值、一句话、一个表达式,就代表这就是要return的内容//例子中:{ value: item.price, name: item.name }就是return这么一个对象值//为什么用()包住这个对象?因为对象外层是{},箭头函数会当成这是一个函数体,要用()包起来//然后为什么要修改list数组的值?//因为前面我们把网络数据返回的内容给到了data设的数组list//然后我们要去用console.log()检查这些数据有什么内容,哪些有用要,哪些没用不要//然后发现echarts需要的data的配置参数只有value和name这两个参数//那我们就只提取出list的每一个对象成员的符合value和name这两个参数要的值//然后把list的每一个对象成员设置成{ value: xxx, name: xxx }这种形式,就符合echarts示例所需要得到配置参数要求了}]})
},
这里先解释一下.map()函数是什么意思
.map()函数是遍历数组每个成员,然后return一个经过修改的值,作为遍历到的这个成员的新值。item是自定义的,代表遍历到的数组的每一个成员
然后()=>箭头函数如果是一个值、一句话、一个表达式,就代表这就是要return的内容
例子中:{ value: item.price, name: item.name }就是return这么一个对象值
为什么用()包住这个对象?因为对象外层是{},箭头函数会当成这是一个函数体,要用()包起来
然后为什么要修改list数组的值?
因为前面我们把网络数据返回的内容给到了data设的数组list,然后我们要去用console.log()检查这些数据有什么内容,哪些有用要,哪些没用不要
然后发现echarts需要的data的配置参数只有value和name这两个参数,那我们就只提取出list的每一个对象成员的符合value和name这两个参数要的值
然后把list的每一个对象成员设置成{ value: xxx, name: xxx }这种形式,就符合echarts示例所需要得到配置参数要求了
兄弟们我解释得很透彻很幸苦,各位好好看,点个赞
另外把整个例子完整代码放这里:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><!-- CSS only --><linkrel="stylesheet"href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/><style>.red {color: red!important;}.search {width: 300px;margin: 20px 0;}.my-form {display: flex;margin: 20px 0;}.my-form input {flex: 1;margin-right: 20px;}.table > :not(:first-child) {border-top: none;}.contain {display: flex;padding: 10px;}.list-box {flex: 1;padding: 0 30px;}.list-box a {text-decoration: none;}.echarts-box {width: 600px;height: 400px;padding: 30px;margin: 0 auto;border: 1px solid #ccc;}tfoot {font-weight: bold;}@media screen and (max-width: 1000px) {.contain {flex-wrap: wrap;}.list-box {width: 100%;}.echarts-box {margin-top: 30px;}}</style></head><body><div id="app"><div class="contain"><!-- 左侧列表 --><div class="list-box"><!-- 添加资产 --><form class="my-form"><input v-model.trim="name" type="text" class="form-control" placeholder="消费名称" /><input v-model.number="price" type="text" class="form-control" placeholder="消费价格" /><button @click="add" type="button" class="btn btn-primary">添加账单</button></form><table class="table table-hover"><thead><tr><th>编号</th><th>消费名称</th><th>消费价格</th><th>操作</th></tr></thead><tbody><tr v-for="(item, index) in list" :key="item.id"><td>{{ index + 1 }}</td><td>{{ item.name }}</td><td :class="{ red: item.price > 500 }">{{ item.price.toFixed(2) }}</td><td><a @click="del(item.id)" href="javascript:;">删除</a></td></tr></tbody><tfoot><tr><td colspan="4">消费总计: {{ totalPrice.toFixed(2) }}</td></tr></tfoot></table></div><!-- 右侧图表 --><div class="echarts-box" id="main"></div></div></div><script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script>/*** 接口文档地址:* https://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc-8df8-0aff8dc317a8/api-53371058* * 功能需求:* 1. 基本渲染* (1) 立刻发送请求获取数据 created* (2) 拿到数据,存到data的响应式数据中* (3) 结合数据,进行渲染 v-for* (4) 消费统计 => 计算属性* 2. 添加功能* (1) 收集表单数据 v-model* (2) 给添加按钮注册点击事件,发送添加请求* (3) 需要重新渲染* 3. 删除功能* (1) 注册点击事件,传参传 id* (2) 根据 id 发送删除请求* (3) 需要重新渲染* 4. 饼图渲染* (1) 初始化一个饼图 echarts.init(dom) mounted钩子实现* (2) 根据数据实时更新饼图 echarts.setOption({ ... })*/const app = new Vue({el: '#app',data: {list: [],name: '',price: ''},computed: {totalPrice () {return this.list.reduce((sum, item) => sum + item.price, 0)}},created () {// const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {// params: {// creator: '小黑'// }// })// this.list = res.data.datathis.getList()},mounted () {this.myChart = echarts.init(document.querySelector('#main'))this.myChart.setOption({// 大标题title: {text: '消费账单列表',left: 'center'},// 提示框tooltip: {trigger: 'item'},// 图例legend: {orient: 'vertical',left: 'left'},// 数据项series: [{name: '消费账单',type: 'pie',radius: '50%', // 半径data:[{ value: 1048, name: '球鞋' },{ value: 735, name: '防晒霜' }],emphasis: {itemStyle: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}]})},methods: {async getList () {const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {params: {creator: '小黑'}})this.list = res.data.dataconsole.log(res.data.data)console.log(this.list)// 更新图表this.myChart.setOption({// 数据项series: [{// data: [// { value: 1048, name: '球鞋' },// { value: 735, name: '防晒霜' }// ]data: this.list.map(item => ({ value: item.price, name: item.name}))//这里这么写是因为//看echarts的这个示例的源码的配置数据可以知道,在这个配置数据的data这里只能有value和name这两个参数//然后我们console.log可以看到我们拿到的对象数据里很乱,什么值都有,但是没有value这个参数名(name刚好有)//但是我们打印输出可以注意到,对象里的price值就对应着value要的值,name值对应name要的值//那么只是名字不一样,而且还有别的多余的参数,那就把获取到对象数据的list数组修改一下里面的内容//用map函数,item是自定义的,代表遍历到数组的每一个成员,那么item.price不就是这个对象成员的price项吗//这样一来list数组每个对象成员就变成{ value: xxx, name: xxx }这种形式了,就符合echarts示例所需要得到配置参数要求了}]})},async add () {console.log(this.list)if (!this.name) {alert('请输入消费名称')return}if (typeof this.price !== 'number') {alert('请输入正确的消费价格')return}// 发送添加请求const res = await axios.post('https://applet-base-api-t.itheima.net/bill', {creator: '小黑',name: this.name,price: this.price})// 重新渲染一次this.getList()this.name = ''this.price = ''},async del (id) {// 根据 id 发送删除请求const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)// 重新渲染this.getList()}}})</script></body>
</html>