day05-报表技术-图形报表
1、图表报表简介
在大数据时代,人们需要对大量的数据进行分析,帮助用户或公司领导更直观的察觉差异,做出判断,减少时间成本,而在web项目中除了表格显示数据外,还可以通过图表来表现数据,这种图表形式表现数据使人看的清楚明白且更加直观。对于web项目展示图形报表使用最多的技术就是基于js的前端报表框架,目前前端市场使用最多的图形报表框架有:JfreeChart、ECharts、Highcharts、FusionCharts、amCharts等。
2、JFreechart
2.1 简介
JFreeChart是JAVA平台上的一个开放的图表绘制类库。它完全使用JAVA语言编写,可生成饼图(pie charts)、柱状图(bar charts)、散点图(scatter plots)、时序图(time series)、甘特图(Gantt charts)等等多种图表,并且可以产生PNG和JPEG格式的输出,还可以与PDF或EXCEL关联。
2.2 入门Demo
需要的依赖:
<dependency><groupId>org.jfree</groupId><artifactId>jfreechart</artifactId><version>1.5.0</version>
</dependency>
2.2.1 饼图&3D饼图
package com.itheima.test;import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.data.general.DefaultPieDataset;import java.awt.*;
import java.io.File;public class JfreeChartsDemo1 {public static void main(String[] args) throws Exception {
//构建饼图的数据集DefaultPieDataset dataset=new DefaultPieDataset();dataset.setValue("销售部", 120);dataset.setValue("人事部", 50);dataset.setValue("技术部", 180);StandardChartTheme standardChartTheme=new StandardChartTheme("CN");//设置标题字体standardChartTheme.setExtraLargeFont(new Font("华文宋体",Font.BOLD,20));//设置图例的字体standardChartTheme.setRegularFont(new Font("华文宋体", Font.BOLD,15));//设置轴向的字体standardChartTheme.setLargeFont(new Font("华文宋体",Font.BOLD,15));//应用主题样式ChartFactory.setChartTheme(standardChartTheme);
//参数1 title 标题
//参数2 dataset 数据集
//参数3 是否开启图例
//参数4 是否开启工具栏
//参数5 是否开启url跳转
// JFreeChart chart= ChartFactory.createPieChart("各部门人数", dataset, true, false, false);JFreeChart chart= ChartFactory.createPieChart3D("各部门人数", dataset, true, false, false);
//生成一张图表的图片文件ChartUtils.saveChartAsPNG(new File("d:\\chart1.png"), chart, 400, 300);}
}
效果图:
3D效果图
2.2.2 折线图
package com.itheima.test;import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.Dataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.DefaultValueDataset;import java.awt.*;
import java.io.File;public class JfreeChartsDemo2 {public static void main(String[] args) throws Exception {
//构建饼图的数据集DefaultCategoryDataset dataset=new DefaultCategoryDataset();dataset.addValue(15,"技术部","2011");dataset.addValue(11,"技术部","2012");dataset.addValue(10,"技术部","2013");dataset.addValue(16,"技术部","2014");dataset.addValue(10,"销售部","2011");dataset.addValue(30,"销售部","2012");dataset.addValue(6,"销售部","2013");dataset.addValue(16,"销售部","2014");dataset.addValue(10,"产品部","2011");dataset.addValue(20,"产品部","2012");dataset.addValue(30,"产品部","2013");dataset.addValue(15,"产品部","2014");StandardChartTheme standardChartTheme=new StandardChartTheme("CN");//设置标题字体standardChartTheme.setExtraLargeFont(new Font("华文宋体",Font.BOLD,20));//设置图例的字体standardChartTheme.setRegularFont(new Font("华文宋体", Font.PLAIN,15));//设置轴向的字体standardChartTheme.setLargeFont(new Font("华文宋体",Font.PLAIN,15));//应用主题样式ChartFactory.setChartTheme(standardChartTheme);
//参数1 title 标题
//参数2 x轴的说明
//参数3 Y轴的说明
//参数4 数据集JFreeChart chart= ChartFactory.createLineChart("入职人数", "年度", "人数", dataset);
//生成一张图表的图片文件ChartUtils.saveChartAsPNG(new File("d:\\chart2.png"), chart, 400, 300);}
}
效果图:
2.2.3 柱状图(条形图)
package com.itheima.test;import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.data.category.DefaultCategoryDataset;import java.awt.*;
import java.io.File;public class JfreeChartsDemo3 {public static void main(String[] args) throws Exception {
//构建饼图的数据集DefaultCategoryDataset dataset=new DefaultCategoryDataset();dataset.addValue(15,"技术部","2011");dataset.addValue(11,"技术部","2012");dataset.addValue(10,"技术部","2013");dataset.addValue(16,"技术部","2014");dataset.addValue(10,"销售部","2011");dataset.addValue(30,"销售部","2012");dataset.addValue(6,"销售部","2013");dataset.addValue(16,"销售部","2014");dataset.addValue(10,"产品部","2011");dataset.addValue(20,"产品部","2012");dataset.addValue(30,"产品部","2013");dataset.addValue(15,"产品部","2014");StandardChartTheme standardChartTheme=new StandardChartTheme("CN");//设置标题字体standardChartTheme.setExtraLargeFont(new Font("华文宋体",Font.BOLD,20));//设置图例的字体standardChartTheme.setRegularFont(new Font("华文宋体", Font.PLAIN,15));//设置轴向的字体standardChartTheme.setLargeFont(new Font("华文宋体",Font.PLAIN,15));//应用主题样式ChartFactory.setChartTheme(standardChartTheme);
//参数1 title 标题
//参数2 x轴的说明
//参数3 Y轴的说明
//参数4 数据集JFreeChart chart= ChartFactory.createBarChart("入职人数", "年度", "人数", dataset);
//生成一张图表的图片文件ChartUtils.saveChartAsPNG(new File("d:\\chart3.png"), chart, 400, 300);}
}
效果图:
3、Highcharts
3.1 简介
Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习、个人网站和非商业用途使用。HighCharts支持的图表类型有曲线图、区域图、柱状图、饼状图、散状点图和综合图表。
3.2 下载安装
官网下载: https://www.highcharts.com.cn/download
1、下载
2、解压
3、把js放入到项目中
3.3 入门案例
第一步:创建一个html demo.html
第二步:页面中引入js文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="js/highcharts.js"></script>
</head>
<body></body>
</html>
第三步:准备一个dom
<body>
<div id="container" style="width: 600px;height:400px;"></div>
</body>
第四步:js代码
<script>// 图表配置var options = {chart: {type: 'bar' //指定图表的类型,默认是折线图(line)},title: {text: '我的第一个图表' // 标题},xAxis: {categories: ['苹果', '香蕉', '橙子'] // x 轴分类},yAxis: {title: {text: '吃水果个数' // y 轴标题}},series: [{ // 数据列name: '小明', // 数据列名data: [1, 0, 4] // 数据}, {name: '小红',data: [5, 7, 3]}]};// 图表初始化函数var chart = Highcharts.chart('container', options);</script>
运行结果:
属性解释:
(1)chart :图表基本属性a) plotBackgroundColor 区域背景颜色b) plotBorderWidth 区域边框宽度c) plotShadow 区域阴影d) type 图表类型
(2)title :图表标题a) text 标题文本
(3)tooltip :工具提示a) pointFormat 工具提示显示格式
(4)plotOptions:区域选项a) allowPointSelect 点击区域后选择b) cursor 光标类型c) dataLabels 数据标签d) showInLegend 是否显示图例
(5)series: 数据组a) name 名称b) colorByPoint 点的颜色c) data 数据
3.4 准备页面
在static文件夹下创建页面echarts_index.html ,内容如下
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no,minimal-ui" /><title>highcharts图表报表</title><link rel="stylesheet" href="css/charts_demo.css"><script src="js/vuejs-2.5.16.js"></script><script src="js/axios-0.18.0.js"></script><script src="js/highcharts.js"></script><script src="js/highcharts-3d.js"></script><script src="js/highcharts-more.js"></script><script src="js/drilldown.js"></script></head>
<body>
<div id="app" class="my-box"><div class="my-box-left"><button @click="columnCharts">统计各部门人数</button> <br/> <br/><button @click="lineCharts">月份入职人数统计</button> <br/> <br/><button @click="pieCharts">员工地方来源统计</button> <br/> <br/></div><div class="my-box-right"><div id="container" style="height:450px;"></div></div>
</div>
</body>
<script>new Vue({el:"#app",data:{},methods: {columnCharts() {},lineCharts(){},pieCharts(){}}
});
</script>
</html>
3.5 统计各部门人数(柱状图)
第一步:准备sql语句:用户表和部门表关联查询,根据部门名称分组统计
select dept_name deptName,count(u.id) num from tb_dept d LEFT JOIN tb_user u on d.id=u.dept_id GROUP BY dept_name
第二步:后台代码
1、创建一个新的StatController
package com.itheima.controller;import com.itheima.service.StatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/stat")
public class StatController {@Autowiredprivate StatService statService;@GetMapping(value = "/columnCharts",name = "统计各部门人数,柱状图")public List<Map> columnCharts(){return statService.columnCharts();}
}
2、创建StatService
package com.itheima.service;import com.itheima.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.Map;@Service
public class StatService {@Autowiredprivate UserMapper userMapper;public List<Map> columnCharts() {return userMapper.columnCharts();}
}
3、UserMapper定义方法
@Select(value = "select dept_name deptName,count(u.id) num from tb_dept d LEFT JOIN tb_user u on d.id=u.dept_id GROUP BY dept_name")List<Map> columnCharts();
第三步:完成js方法
在highcharts_index.html页面中参考highcharts官网上的柱状图完成以下代码
https://www.highcharts.com.cn/demo/highcharts/column-basic
methods: {columnCharts() {axios.get("/stat/columnCharts").then(res => {let datas = res.data;let titles=[]; //x轴上显示的数据let values=[]; //y轴上显示的数据for (let i = 0; i < datas.length; i++) {titles[i] = datas[i].deptName;values[i] = datas[i].num;}Highcharts.chart('container', {chart: {type: 'column'},title: {text: '各部门人数'},xAxis: {categories:titles,crosshair: true},yAxis: {min: 0,title: {text: '人数'}},tooltip: {// head + 每个 point + footer 拼接成完整的 tableheaderFormat: '<span style="font-size:10px">{point.key}</span><table>',pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +'<td style="padding:0"><b>{point.y:.1f} </b></td></tr>',footerFormat: '</table>',shared: true,useHTML: true},plotOptions: {column: {borderWidth: 0}},series: [{name: '各部门人数',data: values}]});})},pieCharts(){},lineCharts(){}}
最后效果:
3.6 月份入职人数统计(折线图)
第一步:准备SQL语句
一年12个月,想知道什么月份入职的人员最后
select m.name,IFNULL(t.num,0) num from tb_month m LEFT JOIN (
select DATE_FORMAT(hire_date,'%m') months ,count(id) num from tb_user GROUP BY DATE_FORMAT(hire_date,'%m')
) t ON m.name=t.months
第二步:完成后台代码
1、StatController添加方法
@GetMapping(value = "/lineCharts",name = "月份入职人数统计,折线图")
public List<Map> lineCharts(){return statService.lineCharts();
}
2、StatService添加方法
public List<Map> lineCharts() {return userMapper.lineCharts();
}
3、UserMapper添加方法
@Select("select m.name,IFNULL(t.num,0) num from tb_month m LEFT JOIN ( " +"select DATE_FORMAT(hire_date,'%m') months ,count(id) num from tb_user GROUP BY DATE_FORMAT(hire_date,'%m') " +") t ON m.name=t.months")
List<Map> lineCharts();
第三步:完成js代码
在highcharts_index.html页面中参考highcharts官网上的柱状图完成以下代码
https://www.highcharts.com.cn/demo/highcharts/line-basic
lineCharts(){axios.get("/stat/lineCharts").then(res=>{let datas = res.data;let values=[]; //y轴上显示的数据for (let i = 0; i < datas.length; i++) {values[i] = datas[i].num;}var chart = Highcharts.chart('container', {title: {text: '月份入职人数统计'},yAxis: {title: {text: '入职人数'}},legend: {layout: 'vertical',align: 'right',verticalAlign: 'middle'},plotOptions: {series: {label: {connectorAllowed: false},pointStart: 2010}},series: [{name: '入职人数',data: values}],responsive: {rules: [{condition: {maxWidth: 500},chartOptions: {legend: {layout: 'horizontal',align: 'center',verticalAlign: 'bottom'}}}]}});})
}
效果:
3.7 员工地方来源统计(可下钻的饼状图)
统计公司员工的来源
第一步:环境准备
什么是下钻的效果
https://www.highcharts.com.cn/demo/highcharts/column-drilldown
https://www.highcharts.com.cn/demo/highcharts/pie-drilldown
如果想要下钻的效果,需要在多引入一个js,从下载的压缩包中找到后放到项目中,并且在html中引入
<script src="js/drilldown.js"></script>
第二步:后台方法准备数据
1、StatController代码添加方法
@GetMapping(value = "/pieCharts",name = "公司员工地方来源,包括省、市")
public List<Map> pieCharts(){return statService.pieCharts();
}
3、StatService中添加方法
这个方法直接返回js上需要的所有数据
[{id:“河北省”,“drilldown”:“河北省”,“name”:“河北省”,“y”:10,“data”:[{“name”:“石家庄”,“y”:4},{“name”:“唐山”,“y”:3},{“name”:“保定”,“y”:3}]}]
public List<Map> pieCharts() {List<Map> resultMapList = new ArrayList();
// 最终想要的数据格式:[{id:"河北省","drilldown":"河北省","name":"河北省","y":10,"data":[{"name":"石家庄","y":4},{"name":"唐山","y":3},{"name":"保定","y":3}]}]List<User> userList = userMapper.selectAll(); //查询所有员工数据
// 根据省份分组Map<String, List<User>> provinceMap = userList.stream().collect(Collectors.groupingBy(User::getProvince));for (String provinceName : provinceMap.keySet()) {int provinceSize = 0;Map resultMap = new HashMap();resultMap.put("id",provinceName);resultMap.put("drilldown",provinceName);resultMap.put("name",provinceName);
// 再根据城市分组Map<String, List<User>> cityMap = provinceMap.get(provinceName).stream().collect(Collectors.groupingBy(User::getCity));List<Map> dataMapList = new ArrayList<>();for (String cityName : cityMap.keySet()) {Map dataMap = new HashMap();dataMap.put("name",cityName);int citySize = cityMap.get(cityName).size();dataMap.put("y",citySize);dataMapList.add(dataMap);provinceSize+=citySize;}resultMap.put("y",provinceSize);resultMap.put("data",dataMapList);resultMapList.add(resultMap);}return resultMapList;}
第三步:完成js代码
pieCharts(){axios.get("/stat/pieCharts").then(res=>{let datas = res.data;Highcharts.chart('container', {chart: {type: 'column'},title: {text: '公司原因地方来源'},xAxis: {type: 'category'},yAxis: {title: {text: '人数'}},legend: {enabled: false},plotOptions: {series: {borderWidth: 0,dataLabels: {enabled: true,format: '{point.y}'}}},tooltip: {headerFormat: '<span style="font-size:11px">{series.name}</span><br>',pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y}</b><br/>'},series: [{name: '省份',colorByPoint: true,data: datas}],drilldown: {series: datas}});})}
效果:
点击河北省
4、Echarts
4.1 简介
ECharts是由百度前端团队开发的一款开源的基于js图形报表组件,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖轻量级的矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。
ECharts 特性:
丰富的可视化类型
多种数据格式无需转换直接使用
千万数据的前端展现
移动端优化
多渲染方案,跨平台使用!
深度的交互式数据探索
多维数据的支持以及丰富的视觉编码手段
动态数据
绚丽的特效
4.2 下载安装
1、下载js
https://github.com/apache/incubator-echarts/tree/4.7.0
或 从 npm 安装 (前提是电脑上有node环境)
npm install echarts
2、把下载好的js放入到项目中
4.3 入门案例
第一步 导入js依赖
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><!-- 引入 ECharts 文件 --><script src="js/echarts.min.js"></script>
</head>
</html>
4.3.2 配置dom容器
在绘图前我们需要为 ECharts 准备一个具备高宽的 DOM 容器。
<body><!-- 为 ECharts 准备一个具备大小(宽高)的 DOM --><div id="main" style="width: 600px;height:400px;"></div>
</body>
4.3.3 初始化图形
然后就可以通过 echarts.init 方法初始化一个 echarts 实例并通过 setOption 方法生成一个简单的柱状图,下面是完整代码。
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>ECharts</title><!-- 引入 echarts.js --><script src="echarts.min.js"></script>
</head>
<body><!-- 为ECharts准备一个具备大小(宽高)的Dom --><div id="main" style="width: 600px;height:400px;"></div><script type="text/javascript">// 基于准备好的dom,初始化echarts实例var myChart = echarts.init(document.getElementById('main'));// 指定图表的配置项和数据var option = {title: {text: 'ECharts 入门示例'},tooltip: {},legend: {data:['销量']},xAxis: {data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]},yAxis: {},series: [{name: '销量',type: 'bar',data: [5, 20, 36, 10, 10, 20]}]};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);</script>
</body>
</html>
效果:
4.4 准备页面
在static下新建一个页面echarts_index.html 内容如下
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no,minimal-ui" /><title>echarts图表报表</title><link rel="stylesheet" href="css/charts_demo.css"><script src="js/vuejs-2.5.16.js"></script><script src="js/axios-0.18.0.js"></script><script src="js/echarts.min.js"></script></head>
<body>
<div id="app" class="my-box"><div class="my-box-left"><button @click="columnCharts">统计各部门人数</button> <br/> <br/><button @click="lineCharts">月份入职人数统计</button> <br/> <br/><button @click="pieCharts">员工地方来源统计</button> <br/> <br/><button @click="mapCharts">员工地方来源统计(地图)</button> <br/> <br/></div><div class="my-box-right"><div id="container" style="height:450px;"></div></div>
</div>
</body>
<script>new Vue({el:"#app",data:{},methods: {columnCharts() {},lineCharts(){},pieCharts(){},mapCharts(){}}});
</script>
</html>
4.5 统计各部门人数(柱状图)
官网参考 https://echarts.apache.org/examples/zh/editor.html?c=bar-simple
可以直接使用3.5小结highcharts的后台方法
修改echarts_index.html中的js方法
columnCharts() {axios.get("/stat/columnCharts").then(res=>{let datas = res.data;let titles=[]; //x轴上显示的数据let values=[]; //y轴上显示的数据for (let i = 0; i < datas.length; i++) {titles[i] = datas[i].deptName;values[i] = datas[i].num;}var myChart = echarts.init(document.getElementById('container'));// 指定图表的配置项和数据var option = {title: {text: '各部门人数'},tooltip: {},legend: {data:['人数']},xAxis: {data: titles},yAxis: {},series: [{name: '人数',type: 'bar',data: values}]};// 使用刚指定的配置项和数据显示图表。myChart.clear();myChart.setOption(option);})
}
效果:
4.6 月份入职人数统计(折线图)
官网参考 https://echarts.apache.org/examples/zh/editor.html?c=line-simple
可以直接使用3.6小结highcharts的后台方法
修改echarts_index.html中的js方法
lineCharts(){axios.get("/stat/lineCharts").then(res=>{let datas = res.data;let titles=[]; //x轴上显示的数据let values=[]; //y轴上显示的数据for (let i = 0; i < datas.length; i++) {titles[i] = datas[i].name;values[i] = datas[i].num;}var myChart = echarts.init(document.getElementById('container'));option = {xAxis: {type: 'category',data: titles},yAxis: {type: 'value'},series: [{data: values,type: 'line'}]};// 使用刚指定的配置项和数据显示图表。myChart.clear();myChart.setOption(option);})
}
4.7 员工地方来源统计(饼图)
Echarts没有提供下钻的效果,但是有一个和下钻类似的效果
官网参考 https://echarts.apache.org/examples/zh/editor.html?c=pie-nest
安装官网上给的参考数据,会发现需要用到三种数据:省份集合、城市集合、城市名称集合
第一步:根据需求后台提供数据
1、StatController新添加一个方法
@GetMapping(value = "/pieECharts",name = "公司员工地方来源,包括省、市")
public Map pieECharts(){return statService.pieECharts();
}
2、StatService处理数据
public Map pieECharts() {Map resultMap = new HashMap();// 最终想要的数据格式:{province:[{name:,value:}],city:[]}Example example = new Example(User.class);example.setOrderByClause("province , city");List<User> userList = userMapper.selectByExample(example); //查询所有员工数据// 根据省份分组List<Map> provinceMapList = new ArrayList<>();// 注意分组时得排序,不然数据会乱Map<String, List<User>> provinceMap = userList.stream().collect(Collectors.groupingBy(User::getProvince,LinkedHashMap::new,Collectors.toList()));for (String provinceName : provinceMap.keySet()) {Map map = new HashMap();map.put("name",provinceName);map.put("value",provinceMap.get(provinceName).size());provinceMapList.add(map);}List<Map> cityMapList = new ArrayList<>();// 注意分组时得排序,不然数据会乱Map<String, List<User>> cityMap = userList.stream().collect(Collectors.groupingBy(User::getCity, LinkedHashMap::new,Collectors.toList()));for (String cityName : cityMap.keySet()) {Map map = new HashMap();map.put("name",cityName);map.put("value",cityMap.get(cityName).size());cityMapList.add(map);}resultMap.put("province",provinceMapList);resultMap.put("city",cityMapList);return resultMap;
}
第二步:完成JS代码
pieCharts(){axios.get("/stat/pieECharts").then(res=>{let datas = res.data;// 需要三种数据:都可以从datas中获取// 1、省份数据 [{name:"河北省",value:10}]// 2、城市数据 [{name:"石家庄",value:3}]// 3、城市的名称let provinceData = datas.province;let cityData = datas.city;let cityNames = [];for (let i = 0; i < cityData.length; i++) {cityNames[i] = cityData[i].name;}var myChart = echarts.init(document.getElementById('container'));option = {tooltip: {trigger: 'item',formatter: '{a} <br/>{b}: {c} ({d}%)'},legend: {orient: 'vertical',left: 10,data: cityNames},series: [{name: '员工来源',type: 'pie',selectedMode: 'single',radius: [0, '30%'],label: {position: 'inner'},labelLine: {show: false},data: provinceData},{name: '员工来源',type: 'pie',radius: ['40%', '55%'],label: {formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',backgroundColor: '#eee',borderColor: '#aaa',borderWidth: 1,borderRadius: 4,// shadowBlur:3,// shadowOffsetX: 2,// shadowOffsetY: 2,// shadowColor: '#999',// padding: [0, 7],rich: {a: {color: '#999',lineHeight: 22,align: 'center'},// abg: {// backgroundColor: '#333',// width: '100%',// align: 'right',// height: 22,// borderRadius: [4, 4, 0, 0]// },hr: {borderColor: '#aaa',width: '100%',borderWidth: 0.5,height: 0},b: {fontSize: 16,lineHeight: 33},per: {color: '#eee',backgroundColor: '#334455',padding: [2, 4],borderRadius: 2}}},data: cityData}]};// 使用刚指定的配置项和数据显示图表。myChart.clear();myChart.setOption(option);})
}
4.8 员工地方来源统计(中国地图)
直接使用4.7小结提供的后台数据
第一步:参考官网源码引用js
https://echarts.apache.org/examples/zh/editor.html?c=map-polygon
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script><script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=UzpZ9A94pysSfj013URfjCfeUKjMv52F"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/bmap.min.js"></script>
第二步:修改js代码
mapCharts(){axios.get("/stat/pieECharts").then(res=>{var myChart = echarts.init(document.getElementById('container'));var data = res.data.city;for (let i = 0; i < data.length; i++) {data[i].name = data[i].name.substring(0,data[i].name.length-1);data[i].value = data[i].value; }var geoCoordMap = {'海门':[121.15,31.89],'鄂尔多斯':[109.781327,39.608266],'招远':[120.38,37.35],'舟山':[122.207216,29.985295],'齐齐哈尔':[123.97,47.33],'盐城':[120.13,33.38],'赤峰':[118.87,42.28],'青岛':[120.33,36.07],'乳山':[121.52,36.89],'金昌':[102.188043,38.520089],'泉州':[118.58,24.93],'莱西':[120.53,36.86],'日照':[119.46,35.42],'胶南':[119.97,35.88],'南通':[121.05,32.08],'拉萨':[91.11,29.97],'云浮':[112.02,22.93],'梅州':[116.1,24.55],'文登':[122.05,37.2],'上海':[121.48,31.22],'攀枝花':[101.718637,26.582347],'威海':[122.1,37.5],'承德':[117.93,40.97],'厦门':[118.1,24.46],'汕尾':[115.375279,22.786211],'潮州':[116.63,23.68],'丹东':[124.37,40.13],'太仓':[121.1,31.45],'曲靖':[103.79,25.51],'烟台':[121.39,37.52],'福州':[119.3,26.08],'瓦房店':[121.979603,39.627114],'即墨':[120.45,36.38],'抚顺':[123.97,41.97],'玉溪':[102.52,24.35],'张家口':[114.87,40.82],'阳泉':[113.57,37.85],'莱州':[119.942327,37.177017],'湖州':[120.1,30.86],'汕头':[116.69,23.39],'昆山':[120.95,31.39],'宁波':[121.56,29.86],'湛江':[110.359377,21.270708],'揭阳':[116.35,23.55],'荣成':[122.41,37.16],'连云港':[119.16,34.59],'葫芦岛':[120.836932,40.711052],'常熟':[120.74,31.64],'东莞':[113.75,23.04],'河源':[114.68,23.73],'淮安':[119.15,33.5],'泰州':[119.9,32.49],'南宁':[108.33,22.84],'营口':[122.18,40.65],'惠州':[114.4,23.09],'江阴':[120.26,31.91],'蓬莱':[120.75,37.8],'韶关':[113.62,24.84],'嘉峪关':[98.289152,39.77313],'广州':[113.23,23.16],'延安':[109.47,36.6],'太原':[112.53,37.87],'清远':[113.01,23.7],'中山':[113.38,22.52],'昆明':[102.73,25.04],'寿光':[118.73,36.86],'盘锦':[122.070714,41.119997],'长治':[113.08,36.18],'深圳':[114.07,22.62],'珠海':[113.52,22.3],'宿迁':[118.3,33.96],'咸阳':[108.72,34.36],'铜川':[109.11,35.09],'平度':[119.97,36.77],'佛山':[113.11,23.05],'海口':[110.35,20.02],'江门':[113.06,22.61],'章丘':[117.53,36.72],'肇庆':[112.44,23.05],'大连':[121.62,38.92],'临汾':[111.5,36.08],'吴江':[120.63,31.16],'石嘴山':[106.39,39.04],'沈阳':[123.38,41.8],'苏州':[120.62,31.32],'茂名':[110.88,21.68],'嘉兴':[120.76,30.77],'长春':[125.35,43.88],'胶州':[120.03336,36.264622],'银川':[106.27,38.47],'张家港':[120.555821,31.875428],'三门峡':[111.19,34.76],'锦州':[121.15,41.13],'南昌':[115.89,28.68],'柳州':[109.4,24.33],'三亚':[109.511909,18.252847],'自贡':[104.778442,29.33903],'吉林':[126.57,43.87],'阳江':[111.95,21.85],'泸州':[105.39,28.91],'西宁':[101.74,36.56],'宜宾':[104.56,29.77],'呼和浩特':[111.65,40.82],'成都':[104.06,30.67],'大同':[113.3,40.12],'镇江':[119.44,32.2],'桂林':[110.28,25.29],'张家界':[110.479191,29.117096],'宜兴':[119.82,31.36],'北海':[109.12,21.49],'西安':[108.95,34.27],'金坛':[119.56,31.74],'东营':[118.49,37.46],'牡丹江':[129.58,44.6],'遵义':[106.9,27.7],'绍兴':[120.58,30.01],'扬州':[119.42,32.39],'常州':[119.95,31.79],'潍坊':[119.1,36.62],'重庆':[106.54,29.59],'台州':[121.420757,28.656386],'南京':[118.78,32.04],'滨州':[118.03,37.36],'贵阳':[106.71,26.57],'无锡':[120.29,31.59],'本溪':[123.73,41.3],'克拉玛依':[84.77,45.59],'渭南':[109.5,34.52],'马鞍山':[118.48,31.56],'宝鸡':[107.15,34.38],'焦作':[113.21,35.24],'句容':[119.16,31.95],'北京':[116.46,39.92],'徐州':[117.2,34.26],'衡水':[115.72,37.72],'包头':[110,40.58],'绵阳':[104.73,31.48],'乌鲁木齐':[87.68,43.77],'枣庄':[117.57,34.86],'杭州':[120.19,30.26],'淄博':[118.05,36.78],'鞍山':[122.85,41.12],'溧阳':[119.48,31.43],'库尔勒':[86.06,41.68],'安阳':[114.35,36.1],'开封':[114.35,34.79],'济南':[117,36.65],'德阳':[104.37,31.13],'温州':[120.65,28.01],'九江':[115.97,29.71],'邯郸':[114.47,36.6],'临安':[119.72,30.23],'兰州':[103.73,36.03],'沧州':[116.83,38.33],'临沂':[118.35,35.05],'南充':[106.110698,30.837793],'天津':[117.2,39.13],'富阳':[119.95,30.07],'泰安':[117.13,36.18],'诸暨':[120.23,29.71],'郑州':[113.65,34.76],'哈尔滨':[126.63,45.75],'聊城':[115.97,36.45],'芜湖':[118.38,31.33],'唐山':[118.02,39.63],'平顶山':[113.29,33.75],'邢台':[114.48,37.05],'德州':[116.29,37.45],'济宁':[116.59,35.38],'荆州':[112.239741,30.335165],'宜昌':[111.3,30.7],'义乌':[120.06,29.32],'丽水':[119.92,28.45],'洛阳':[112.44,34.7],'秦皇岛':[119.57,39.95],'株洲':[113.16,27.83],'石家庄':[114.48,38.03],'莱芜':[117.67,36.19],'常德':[111.69,29.05],'保定':[115.48,38.85],'湘潭':[112.91,27.87],'金华':[119.64,29.12],'岳阳':[113.09,29.37],'长沙':[113,28.21],'衢州':[118.88,28.97],'廊坊':[116.7,39.53],'菏泽':[115.480656,35.23375],'合肥':[117.27,31.86],'武汉':[114.31,30.52],'大庆':[125.03,46.58]};var convertData = function (data) {var res = [];for (var i = 0; i < data.length; i++) {var geoCoord = geoCoordMap[data[i].name];if (geoCoord) {res.push({name: data[i].name,value: geoCoord.concat(data[i].value)});}}return res;};/* function renderItem(params, api) {var coords = [[116.7,39.53],[103.73,36.03],[112.91,27.87],[120.65,28.01],[119.57,39.95]];var points = [];for (var i = 0; i < coords.length; i++) {points.push(api.coord(coords[i]));}var color = api.visual('color');return {type: 'polygon',shape: {points: echarts.graphic.clipPointsByRect(points, {x: params.coordSys.x,y: params.coordSys.y,width: params.coordSys.width,height: params.coordSys.height})},style: api.style({fill: color,stroke: echarts.color.lift(color)})};}*/option = {backgroundColor: 'transparent',title: {text: '公司员工来源', left: 'center',textStyle: {color: '#fff'}},tooltip : {trigger: 'item'},bmap: {center: [104.114129, 37.550339],zoom: 5,roam: true,mapStyle: {styleJson: [{"featureType": "water","elementType": "all","stylers": {"color": "#044161"}},{"featureType": "land","elementType": "all","stylers": {"color": "#004981"}},{"featureType": "boundary","elementType": "geometry","stylers": {"color": "#064f85"}},{"featureType": "railway","elementType": "all","stylers": {"visibility": "off"}},{"featureType": "highway","elementType": "geometry","stylers": {"color": "#004981"}},{"featureType": "highway","elementType": "geometry.fill","stylers": {"color": "#005b96","lightness": 1}},{"featureType": "highway","elementType": "labels","stylers": {"visibility": "off"}},{"featureType": "arterial","elementType": "geometry","stylers": {"color": "#004981"}},{"featureType": "arterial","elementType": "geometry.fill","stylers": {"color": "#00508b"}},{"featureType": "poi","elementType": "all","stylers": {"visibility": "off"}},{"featureType": "green","elementType": "all","stylers": {"color": "#056197","visibility": "off"}},{"featureType": "subway","elementType": "all","stylers": {"visibility": "off"}},{"featureType": "manmade","elementType": "all","stylers": {"visibility": "off"}},{"featureType": "local","elementType": "all","stylers": {"visibility": "off"}},{"featureType": "arterial","elementType": "labels","stylers": {"visibility": "off"}},{"featureType": "boundary","elementType": "geometry.fill","stylers": {"color": "#029fd4"}},{"featureType": "building","elementType": "all","stylers": {"color": "#1a5787"}},{"featureType": "label","elementType": "all","stylers": {"visibility": "off"}}]}},series : [{name: '人员',type: 'scatter',coordinateSystem: 'bmap',data: convertData(data),symbolSize: function (val) {return val[2] * 100;//数据太小了,为了能显示 把符号扩大了100倍},label: {formatter: '{b}',position: 'right'},itemStyle: {color: '#ddb926'},emphasis: {label: {show: true}}},{name: 'Top 5',type: 'effectScatter',coordinateSystem: 'bmap',data: convertData(data.sort(function (a, b) {return b.value - a.value;}).slice(0, 6)),symbolSize: function (val) {return val[2] / 10;},showEffectOn: 'emphasis',rippleEffect: {brushType: 'stroke'},hoverAnimation: true,label: {formatter: '{b}',position: 'right',show: true},itemStyle: {color: '#f4e925',shadowBlur: 10,shadowColor: '#333'},zlevel: 1},{type: 'custom',coordinateSystem: 'bmap',// renderItem: renderItem,itemStyle: {opacity: 0.5},animation: false,silent: true,data: [0],z: -10}]};// 使用刚指定的配置项和数据显示图表。myChart.clear();myChart.setOption(option);})
}
效果:
相关文章:
day05-报表技术-图形报表
1、图表报表简介 在大数据时代,人们需要对大量的数据进行分析,帮助用户或公司领导更直观的察觉差异,做出判断,减少时间成本,而在web项目中除了表格显示数据外,还可以通过图表来表现数据,这种…...
【Spring】@Transactional事务属性详解
文章目录 1、事务传播行为注意事务传播行为在不同类之间调用生效Propagation.REQUIRED(默认传播行为)Propagation.REQUIRES_NEWPropagation.NESTED 2、事务的隔离级别隔离级别设置 3、设置事务异常回滚3.1、默认情况3.2、设置回滚异常3.3、设置不回滚的异常 4、超时时间5、只读…...
通过css3的锚定滚动属性,实现分页加载时让滚动条不闪动
html标签 <div scroll"handleScroll" id"list-container"style"overflow-anchor:auto;overflow-y: auto;height: 80vh"><ul id"talks"v-for"(item,index) in msgList":key"item.roleiditem.timeitem.conten…...
使用Selenium与Scrapy处理动态加载网页内容的解决方法
博客正文(包含详细注释) 引言 在爬虫技术领域,处理动态加载的网页内容常常是一项挑战,尤其是对于那些通过用户滚动或其他交互动态加载更多内容的网站。本文将介绍如何结合使用Selenium和Scrapy来有效处理这类网页。 初探Seleni…...
Linux的权限(二)
目录 前言 文件类型和访问权限(事物属性) 补充知识 文件类型 文件操作权限 修改文件权限 chmod指令 文件权限值的表示方法 字符表示方法 8进制数值表示方法 权限有无带来的影响 修改文件角色 chown与chgrp指令 目录的rwx权限 补充知识 …...
网络服务IP属地发生变化的原因有哪些?
近期,许多用户发现自己的网络服务IP属地发生了变化。原本固定的IP地址不再是静态的,而是发生了变动。这一现象引起了广大用户的关注和疑惑,对网络服务的使用和信息安全产生了影响。为了解决用户的疑虑,我们对此现象进行了深入探究…...
OpenGL 着色器程序的保存和加载(二进制)
背景 为了提高OpenGL 着色器程序的编译和链接速度,我们可以将程序保存为二进制进行加载,可以大幅度提升加载效率。 方法 以下是加载和保存二进制程序的方法。 // 加载着色器程序的二进制文件到已创建的着色器程序中 bool loadPragram(const std::str…...
【Unity 实用工具篇】| 游戏多语言解决方案,官方插件Localization 实现本地化及多种语言切换
前言 【Unity 实用工具篇】| 游戏多语言解决方案,官方插件Localization 实现本地化及多种语言切换一、多语言本地化插件 Localization1.1 介绍1.2 效果展示1.3 使用说明 二、 插件导入并配置2.1 安装 Localization2.2 全局配置 三、多语言映射表3.1 创建多语言文本配…...
疯狂SQL转换系列- SQL for Tencent Cloud VectorDB
为了尽量保证使用者通过统一的SQL标准访问各类型数据库,我们这里开启了“疯狂SQL转换系列”。转换的语法效果不一定是最好的,更多是为用户提供一个统一的数据库交互体验。转换数据库目标的确认更多是内生的。基于我们对业务发展的需要。该向量库SQL转换的…...
Excel中的INDIRECT函数用法
当在 Excel 中使用 INDIRECT 函数时,它可以帮助我们通过引用字符串中的单元格地址来获取对应单元格的值。这个函数非常有用,特别是在需要动态地引用其他单元格的情况下。下面是 INDIRECT 函数的一些用法和示例: 基本用法: INDIREC…...
Spring-temp
IOC/DI实现步骤 1.配置元数据 2.实例化IOC 3.获取Bean 基于XML配置方式 管理组件 1.基于构造函数:有参、无参 2.基于静态工厂方法:有参、无参 依赖注入 1.构造函数 2.setter方法 Bean组件高级特性 1.作用域 2.生命周期 FactoryBean 基于注解 IOC Bean作…...
【C++干货铺】会搜索的二叉树(BSTree)
个人主页点击直达:小白不是程序媛 C系列专栏:C干货铺 代码仓库:Gitee 目录 前言: 二叉搜索树 二叉搜索树概念 二叉搜索树操作 二叉搜索树的查找 二叉搜索树的插入 二叉搜索树元素的删除 二叉搜索树的实现 BSTree结点 …...
【Spring AOP】 动态代理
一.AOP常见的实现方式 1.Spring AOP 2.aspectJ 注意:spring使用的是aspectJ的注解,但实现是spring自身实现的. 二.AOP原理 Spirng AOP原理 , 基于动态代理实现的. 三.代理模式 作用就是提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类…...
NAT——网络地址转换
目录 一、概念 二、NAT的分类 1.静态NAT 1.1 静态NAT的配置 1.2 利用eNSP小实验加强对静态NAT的理解 2、动态NAT 三、NAPT——端口映射 四、Easy IP 使用一个公网地址可以让所有人都上公网 一、概念 随着Internet的发展和网络应用的增多,IPv4地址枯竭已经成为…...
Lambda 表达式的常见用法
文章目录 Lambda 表达式的常见用法使用Lambda表达式集合遍历使用Lambda表达式排序使用Lambda表达式过滤使用Lambda表达式映射使用Lambda表达式归约使用Lambda表达式分组使用Lambda表达式函数式接口的实现使用Lambda表达式线程的创建使用Lambda表达式进行Optional 操作使用Lambd…...
成本管理常用的ChatGPT通用提示词模板
成本分析:如何进行成本分析? 成本核算:如何进行成本核算? 成本控制:如何控制成本? 成本效益分析:如何进行成本效益分析? 成本预测:如何预测成本? 成本决…...
如何在PHP中处理日期和时间?
在 PHP 中,你可以使用内置的 DateTime 类和相关函数来处理日期和时间。以下是一些常见的日期和时间操作的示例: 使用 DateTime 类: 获取当前日期和时间: $currentDateTime new DateTime(); echo $currentDateTime->format(Y-…...
NO-IOT翻频,什么是翻频,电信为什么翻频
1.1 翻频迁移最终的目的就是减少网络的相互干扰,提供使用质量. 1.2 随着与日俱增的网络规模的扩大,网内干扰已成了影响网络的质量标准之一,为了保障电信上网体验,满足用户日益增长的网速需求,更好的服务客户,电信针对…...
云原生之深入解析OOM和CPU节流
一、前言 使用 Kubernetes 时,内存不足 (OOM) 错误和 CPU 节流是云应用程序中资源处理的主要难题,这是为什么呢?云应用程序中的 CPU 和内存要求变得越来越重要,因为它们与云成本直接相关。通过 limits 和 requests ,可…...
数据结构与算法之递归: LeetCode 93. 复原 IP 地址 (Typescript版)
复原 IP 地址 https://leetcode.cn/problems/restore-ip-addresses/ 描述 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。 例如:“0.1.2.201” 和 “192.…...
json模块与jsonpath详解
数据提取之JSON与JsonPATH JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。 JSON和XML的比较可谓不…...
ubuntu20.04在noetic下编译orbslam2
ubuntu20.04在noetic下编译orbslam2 参考链接1:https://blog.csdn.net/qq_58869016/article/details/128660588 参考链接2:https://blog.csdn.net/dong123456789e/article/details/129693837 在noetic下的安装环境 1.库安装 sudo apt-get update sudo …...
64. 最小路径和
最小路径和 描述 : 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动一步。 题目 : LeetCode 64.最小路径和 64. 最小路径和 解析 : class So…...
惰性加载函数(js的问题)
在web开发中,因为浏览器之间的实现差异,一些嗅探工作总是不可避免。 var addEvent function( elem, type, handler ){if ( window.addEventListener ){return elem.addEventListener( type, handler, false );}if ( window.attachEvent ){return elem.…...
jmeter,读取CSV文件数据的循环控制
1、构造csv数据 保存文件时需要注意文件的编码格式 id,name,limit,status,address,start_time 100,小米100,1000,1,某某会展中心101,2023/8/20 14:20 101,小米101,1001,1,某某会展中心102,2023/8/21 14:20 2、在线程组下添加【CSV数据文件设置】元件 3、CSV文件数据的循环控…...
移植LVGL到像素屏,从此玩转像素屏0门槛
硬件方面 先上渲染图 实物图 配置 主控:esp32 micro32 plus主频:240MhzFlash:8MPSRAM:2M 软件方面 众所周知,LVGL是一个十分优秀的图形框架,小到几百kb的单片机,大到Linux都可以运行。既然它…...
stateflow 之图函数、simulink函数和matlab函数使用及案例分析
目录 前言 1. 图函数graph function 2.simulink function 3.matlab function 4.调用stateflow中的几种函数方式 前言 对于stateflow实际上可以做simulink和matlab的所有任务,可以有matlab的m语言,也可以有simulink的模块,关于几种函数在…...
C# 加载本地文件设置应用程序图标
static class Program{[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Form mainForm new Form1();mainForm.Show();//IntPtr hProcess Process.GetCurrentProcess().MainWindowHandle;// 设置应用程…...
苹果计划将全球1/4的IPhone产能转移至印度
KlipC报道:据相关人士报道,苹果希望在未来2到3年内每年在印度生产超过5000万部iphone,要是该计划得以实现,印度将占领全球iPhone产量的四分之一。 KlipC的分析师Alex Su表示:“此次iPhone15推出是苹果印度制造计划的一…...
el-date-picker 选择一个或多个日期
el-date-picker可选择多个日期 type“dates” 加个s即可 <div><span>el-date-picker选择多个日期</span><el-date-pickertype"dates"v-model"dateList"placeholder"选择一个或多个日期"></el-date-picker></di…...
盱眙有做网站开发的吗/如何建立自己的网站
forin的原理forin语句是JDK5版本的新特性,在此之前,遍历数组或集合的方法有两种:通过下标遍历和通过迭代器遍历。先举个例子:Testpublic void demo() {String arr[] { "abc", "def", "opq" };for …...
哈尔滨免费建站模板/个人网站注册平台
一.角色以及入口: 角色:系统管理员,开发人员 入口:服务管理--修改服务 二.页面元素检查: 对页面初始化的检查,即页面打开后,对页面不做任何操作时的元素检查。(破页;js错;demo对比等…...
照片管理网站模板下载/网站设计需要什么
开发工具是Android Studio,实现了一个中英互译的安卓app,调用科大讯飞的语音识别、语音合成api以及百度翻译api,需要科大讯飞的appid,以及百度翻译的appid和密钥。 App运行截图: 科大讯飞的语音识别、语音合成api调用流程(SDK调用方式)&#…...
现在有哪些网站兼职可以做/百度网站app下载
引用做函数參数 struct Teacher {char name[64];int age ; };void printfT(Teacher *pT) {cout<<pT->age<<endl; }//pT是t1的别名 ,相当于改动了t1 void printfT2(Teacher &pT) {//cout<<pT.age<<endl;pT.age 33; }//pT和t1的是两个不同的变量…...
上海网站备案/爱站网 关键词挖掘工具站
Android开发:如何实现TCP和UDP传输 http://bbs.starandroid.com/showtopic-10667.html Android平台值得关注的开源项目 http://bbs.starandroid.com/showtopic-10668.html Android电源管理相关应用技巧分享 http://bbs.starandroid.com/showtopic-10670…...
高端网站建设域名注册/汕头网站设计公司
p2p思路适应安卓,iOS,web一.SDP配置顺序1.本地PC设置生成offer sdp [localPC offerForConstraints:constraints completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) { }];复制代码将生成sdp通过信令发送给远端并设…...