物联位置选座:ehcarts实现航班选座案例分析
背景
最近在echarts官方看到了一个航班选座的示例,感觉很好,可以扩大,缩小,鼠标放置到座位上可以显示座位号,允许默认选中座位。于是在5.1假期抽了一点点时间,来写一篇文章,深入研究分析一下这个示例,解析一下这个示例的完整代码。首先让我们来看下示例的效果图。
实现思路
代码是使用echarts来实现的,主要用到的是svg和自定义地图的相关知识。
示例的完整代码
在做选座的功能,我们使用div布局加背景图的技术手段也能简单实现,但不支持缩放,在位置比较多,想要看详细的情况下,就需要用到svg,这个可以扩大缩小后不会失真的矢量图形。搭配echarts渲染能力和可扩展性,做出来的功能可以达到很好的用户体验。
这个示例的主要特性大致有以下几点
- 座位默认三种状态,未选的(白色),自己选的(绿色的),已被别人选的(红色)
- 可以扩大,缩小,图片不失真,清晰
- 鼠标放到座位上可以显示座位号
- 可移植性,换个svg文件,就能改成影院选座,或会议室排座
- 简单,快捷,代码只有不到100行
代码分析
获取svg
在示例代码中,首先是要获取一个svg文件。
$.get(ROOT_PATH + '/data/asset/geo/flight-seats.svg', function (svg) {
// ....
})
使用jquery获取一个svg文件,svg的完整路径是
https://cdn.jsdelivr.net/gh/apache/echarts-website@asf-site/examples/data/asset/geo/flight-seats.svg
点击可以访问。但显示的是这样的。
只显示个飞机头,这是因为svg太大的原因。要想看完整的,需要使用专门的svg查看软件。
使用jquery获取的svg,是svg文件的编码。我们可以调试,打印一下svg的内容看一下。
这里可以看到是svg的具体内容。
注册自定义地图
echarts是可以搭配地图来实现自定义的位置坐标布局渲染的。但不仅仅局限于百度,高德地图。他还支持将一个符合地图数据的svg注册为一个地图。
下面来看一下echarts的这个注册自定义地图的api。
registerMap
完整的解释点击此处查看
文档的大致意思就是 你可以配置一个geoJson的东西,然后echarts可以解析内部的坐标,然后渲染,支持查找。
echarts中geo的相关文档。
https://echarts.apache.org/zh/option.html#geo
该组件可以配置一些name,颜色,索引,能否被选中,交互后的颜色,hover效果。
这里稍微扩展一下GeoJSON这个东西,我也是第一次接触。它是一种用于编码各种地理数据结构的格式。
一种编程式的地图,用一些特殊的属性来表达地图上的线,面,点,颜色。区域。
以GeoJSON支持以下几何类型:Point,LineString, Polygon,MultiPoint,MultiLineString,和MultiPolygon。具有其他属性的几何对象是Feature对象。要素集包含在FeatureCollection对象中。
这里说的不对的,欢迎大佬拍砖,传道解惑。
相关文档
这里如果要展开讲的话,以我现在的知识点,肯定讲的不够透彻,如果有感兴趣的同学,可以在评论区留言,下篇文章可以给大家带来有关geojson更详细的解析。
回归主线,那么registerMap这个方法其实就是将svg转化为一个标准的地图坐标系。只不过转化后地图的定位不是根据经纬度,而是因为name。
echarts.registerMap('flight-seats', { svg: svg });
好了上面这句代码的含义就讲解到这里。其实想想,每一个api的后面都牵扯到一大堆的知识。只要你细心,具有探索精神,那就一定会学的比别人多,学的好。知识是连贯的,不是单独存在的。举一反三,融会贯通方得学道。
geo组件的配置
echarts中有很多很多的组件如brush(区域选择组件),parallel(平行坐标系),timeline,calendar(日历坐标系),其中一个就是geo,地理坐标系组件。
地理坐标系组件用于地图的绘制,支持地理坐标系上绘制散点图,线集。
有关geo组件的所有的配置项都可以在此处查询到详细的解析。
此案例使用的就是该组件,那么下面来看下示例是如何配置的。
geo: {
map: 'flight-seats',
roam: true,
selectedMode: 'multiple',
layoutCenter: ['50%', '50%'],
layoutSize: '95%',
tooltip: {
show: true
},
itemStyle: {
color: '#fff'
},
emphasis: {
itemStyle: {
color: null,
borderColor: 'green',
borderWidth: 2
},
label: {
show: false
}
},
select: {
itemStyle: {
color: 'green'
},
label: {
show: false,
textBorderColor: '#fff',
textBorderWidth: 2
}
},
regions: makeTakenRegions(takenSeatNames)
}
以上是示例中有关geo组件的配置,下面让我们仔细分析一下每一个配置项。
map
首先map指向的是我们刚刚注册的一个自定义地图'flight-seats'
map: 'flight-seats',
roam
roam
关键字是用于配置是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
selectedMode
如字面意思selectedMode
字段是用于配置选中模式,表示是否支持多个选中,默认关闭,支持布尔值和字符串,字符串取值可选'single'表示单选,或者'multiple'表示多选。
layoutCenter, layoutSize
用于调整echarts的实例在dom容器中的初始位置。
tooltip
是否开启tooltip效果,开启后,鼠标放到座位上会有文本提示当前座位。
itemStyle
座位的默认样式,配置颜色,字体
emphasis
高亮状态下的多边形和标签样式。
select
选中状态下的多边形和标签样式。
regions
在地图中对特定的区域配置样式。这里传入的是一个数组,被格式化后的已被选的座位信息,
默认已经被选
每一项的数据格式是这样的
{
name: '26E',
silent: true,
itemStyle: {
color: '#bf0e08'
},
emphasis: {
itemStyle: {
borderColor: '#aaa',
borderWidth: 1
}
},
select: {
itemStyle: {
color: '#bf0e08'
}
}
}
其中有一个属性叫做 silent 它的作用是图形是否不响应和触发鼠标事件,默认为 false,即响应和触发鼠标事件。
到这里该示例的echarts配置其实已经讲解完了。这里的坐标系不是用经纬度,而是用每个座位的name来查找的。所以在svg中是可以找到对应的name的。name的值必须保证唯一。
该示例中除了核心的配置外,还有二个辅助函数。一起来看一下。
makeTakenRegions函数
这个函数就是将已经定义好的已选座位数据,转化成格式化的座位样式数据。
下面是定义的默认已被选中的座位。
var takenSeatNames = ['26E', '26D', '26C', '25D', '23C', '21A', '20F'];
geoselectchanged
在这个示例的最后,有一个监听函数
myChart.on('geoselectchanged', function (params) {
var selectedNames = params.allSelected[0].name.slice();
// Remove taken seats.
for (var i = selectedNames.length - 1; i >= 0; i--) {
if (takenSeatNames.indexOf(selectedNames[i]) >= 0) {
selectedNames.splice(i, 1);
}
}
console.log('selected', selectedNames);
});
这几行代码是干嘛的那?
我们在点击座位的时候,是有一个点击事件,这里就是用于处理点击后的交互的,然后获取当前用户选中的座位。
geoselectchanged 世界是 geo 中地图区域切换选中状态的事件。
用户点击选中会触发该事件。 相关文档
我们可以调试一下该函数看下,params的内容具体是什么
这里是用于处理点击已经被人选中的座位,不进行选中,这段函数的使用场景是用于获取当前用户选中的座位列表,比如用户选完座外要将座位信息发送给后台保存。
主要功能就是判断选的座位是不是已经被别人选中了,如果已被选中就剔除。
举一反三
三
分析完代码后,了解了每一个配置项的含义,那么我们趁热打铁做一个类似的联系题,以达到举一反三,融会贯通的目的。
需求,定义一个svg文件,有6个方块,使用它做一个选座位的功能。
定义mysvg文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="600px" height="600px" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g name="a1">
<rect x="20" y="20" rx="20" ry="20" width="100" fill="#cccccc" stroke="#000000" height="100" />
</g>
<g name="a2">
<rect x="20" y="120" rx="20" ry="20" width="100" fill="#cccccc" stroke="#000000" height="100" />
</g>
<g name="a3">
<rect x="20" y="220" rx="20" ry="20" width="100" fill="#cccccc" stroke="#000000" height="100" />
</g>
<g name="a4">
<rect x="20" y="320" rx="20" ry="20" width="100" fill="#cccccc" stroke="#000000" height="100" />
</g>
</svg>
html代码
<div id="main" style="height:600px;width:600px"></div>
<script src="https://cdn.jsdelivr.net/npm/jquery@2.2.4/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script>
var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom);
var option;
$.get('/mysvg.svg', function (svg) {
echarts.registerMap('flight-seats', { svg: svg });
var takenSeatNames = ['a1'];
option = {
tooltip: {
},
geo: {
map: 'flight-seats',
roam: true,
selectedMode: 'multiple',
layoutCenter: ['50%', '50%'],
layoutSize: '95%',
tooltip: {
show: true
},
itemStyle: {
color: '#fff'
},
emphasis: {
itemStyle: {
color: null,
borderColor: 'green',
borderWidth: 2
},
label: {
show: false
}
},
select: {
itemStyle: {
color: 'green'
},
label: {
show: false,
textBorderColor: '#fff',
textBorderWidth: 2
}
},
regions: makeTakenRegions(takenSeatNames)
}
};
function makeTakenRegions(takenSeatNames) {
var regions = [];
for (var i = 0; i < takenSeatNames.length; i++) {
regions.push({
name: takenSeatNames[i],
silent: true,
itemStyle: {
color: '#bf0e08'
},
emphasis: {
itemStyle: {
borderColor: '#aaa',
borderWidth: 1
}
},
select: {
itemStyle: {
color: '#bf0e08'
}
}
});
}
return regions;
}
myChart.setOption(option);
// Get selected seats.
myChart.on('geoselectchanged', function (params) {
var selectedNames = params.allSelected[0].name.slice();
// Remove taken seats.
for (var i = selectedNames.length - 1; i >= 0; i--) {
if (takenSeatNames.indexOf(selectedNames[i]) >= 0) {
selectedNames.splice(i, 1);
}
}
console.log('selected', selectedNames);
});
})
</script>
效果图
注意点
- svg文件必须的每一个座位,可点击区域必须要用g标签包裹,且name属性需定义到g标签上
- 定义geojson时,svg不能指向一个文本
结语
如果掌握了echarts的geo自定义地图,那么你能做出非常多的示例
比如这样的
这样的
还有这样的
只需要一个svg文件,再加几个name,你就可以做成自己想要的地图系图表。
最后送大家一句话:
不积跬步,无以至千里;不积小流,无以成江海
- 分享
- 举报
-
浏览量:2112次2020-07-11 12:17:33
-
浏览量:1618次2020-04-29 15:13:10
-
浏览量:2669次2018-08-14 10:47:38
-
浏览量:1201次2022-12-20 16:17:30
-
浏览量:1074次2023-07-05 10:15:52
-
浏览量:2149次2022-01-13 09:00:14
-
浏览量:3211次2020-07-03 16:09:52
-
浏览量:1920次2020-08-11 21:09:48
-
浏览量:5076次2021-03-31 17:33:56
-
浏览量:3268次2020-12-04 09:34:16
-
浏览量:3777次2020-11-09 15:54:12
-
浏览量:1915次2019-07-25 15:32:35
-
浏览量:970次2024-07-12 08:58:25
-
浏览量:2424次2024-05-17 12:55:02
-
浏览量:2570次2019-10-17 09:48:04
-
浏览量:3452次2020-06-12 09:34:49
-
浏览量:1641次2022-01-31 09:00:12
-
浏览量:1751次2022-03-02 09:00:16
-
浏览量:1611次2022-11-02 16:48:03
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
这把我C
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明