vue echarts實現航班選座案例分析
背景
最近在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/[email protected]/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,你就可以做成自己想要的地圖系圖表。
最後送大傢一句話:
不積跬步,無以至千裡;不積小流,無以成江海
到此這篇關於vue echarts實現航班選座案例分析的文章就介紹到這瞭,更多相關vue echarts航班選座案例內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Vue ECharts實現機艙座位選擇展示功能代碼詳解
- vue+echarts實現中國地圖流動效果(步驟詳解)
- vue+echarts5實現中國地圖的示例代碼
- vue+echarts實現進度條式柱狀圖
- echarts實現餅圖與樣式設置