写了几天,终于在今天早上完成得差不多了,是一个集百度地图,echarts和vue的一个小项目。
具体效果:初始页面为百度地图,左上角有一个checkbox,是一些地点名称,点击勾选一个地点后,使这个地点在地图上标记出来,只是路由跳转而已。点击标记可以跳转到有echarts的页面,有一个tab,可以切换以年月日为横坐标的图表。
这么看起来,算是这段时间学到的东西的综合应用了,感谢老板。(不做完不下班是真的狠)
那些vue的项目环境啊,路由啊,axios,怎么搭建,怎么加载,不会就bing一下。
很重要的问题,地图什么的千万不要写在App.vue上,不然之后的路由会出问题。感谢老部长把我带出坑。
按照我写的过程一步一步来把,现在回过头看,步骤是可以优化的,因为是老板一天一天的给任务,是按照他的任务顺序写出来的。
第一步:写百度地图。相当于之前的百度地图学习,但是比之前的还简单不少,只要获取后台数据并把点渲染到地图上就好了。
整段代码都放上来吧,注释的地方很大程度是我的思考过程,记得要在index.html上引入百度地图的js文件,还有在组件里面给百度地图一个容器div。
created() {
var url = this.HOME;
this.$axios
.post(url)
.then(res => {
this.options = this.$route.query.options;
this.options = this.options == undefined ? [] : this.options;
// console.log(res.data);
this.scope = res.data.data.scope;
// console.log(this.scope);
var agent = navigator.userAgent.toLowerCase();
var flag = agent.match(/(iphone|ipad|android|Touch)/i);
var map = new BMap.Map("allmap");
map.centerAndZoom(new BMap.Point(116.404, 39.915), 12);
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
if (!flag) {
var top_left_navigation = new BMap.NavigationControl(); //左上角,添加默认缩放平移控件
map.addControl(top_left_navigation);
var top_right_navigation = new BMap.NavigationControl({
anchor: BMAP_ANCHOR_TOP_RIGHT,
type: BMAP_NAVIGATION_CONTROL_SMALL
}); //右上角
map.addControl(top_right_navigation);
map.enableScrollWheelZoom(true);
}
// var scope = res.data.data.scope;
// console.log(scope)
var markers = this.markers;
var point = this.point;
for (var i = 0; i < this.scope.length; i++) {
for (var a = 0; a < this.options.length; a++) {
if (i == this.options[a]) {
var p0 = this.scope[i]["longitude"]; //经度
var p1 = this.scope[i]["latitude"]; // 纬度
this.point[i] = new BMap.Point(p0, p1);
// map.panTo(point[i]);
this.markers[i] = new BMap.Marker(point[i]);
map.addOverlay(markers[i]); // 将标注添加到地图中
map.panTo(point[this.options[0]]);
addClickHandler("驻点名称:" + this.scope[i]["name"], markers[i]); //设置点击响应事件
}
}
}
var opts = {
width: 250, // 信息窗口宽度
height: 30, // 信息窗口高度
title: "", // 信息窗口标题
enableMessage: true //设置允许信息窗发送短息
};
// var ifOpen =true;
var _this = this;
function addClickHandler(content, marker) {
marker.addEventListener("click", function(e) {
// openInfo(content, e);
_this.$router.push({ path: "/Charts" });
// setTimeout(function(){
// window.location.href="http://yao.ktvit.cn/yq2.html";
// },500)
});
}
//自动打开信息窗口
// autoOpenInfo('驻点名称:' + this.scope[0]['name'], this.scope[0].longitude,this.scope[0].latitude);
// function autoOpenInfo(content, lng,lat) {
// console.log(lng)
// var point = new BMap.Point(lng, lat);
// var infoWindow = new BMap.InfoWindow(content, opts); // 创建信息窗口对象
// map.openInfoWindow(infoWindow, point); //开启信息窗口
// map.panTo(point);
// }
// function openInfo(content, e) {
// var p = e.target;
// console.log(p)
// console.log(p.getPosition());
// var point = new BMap.Point(p.getPosition().lng, p.getPosition().lat);
// var infoWindow = new BMap.InfoWindow(content, opts); // 创建信息窗口对象
// map.openInfoWindow(infoWindow, point); //开启信息窗口
// map.panTo(point);
// // clickHandler(infoWindow);
// }
this.options = [];
})
.catch(error => {
console.log(error);
});
}
第二步,echarts
在vue里引入echarts,我是参考这篇博客的 https://blog.csdn.net/Amanda_wmy/article/details/79457679
要配置的东西不少。
首先要在vue项目里 install echarts,然后mian.js 文件里面引入echarts组件
// 引入饼状图组件
require('echarts/lib/chart/pie')
// 引入提示框和title组件,图例
require('echarts/lib/component/tooltip')
require('echarts/lib/component/title')
require('echarts/lib/component/legend')
Vue.prototype.$echarts = echarts //引入组件
然后就跟着那个博客的内容写,具体的数据啊那些东西,还是要靠自己。
第三步,三个图表的跳转。
一开始是老板说,点击titile就改变数据的显示,就是点击year就显示年的数据,点击month就显示月的数据。
但是涉及到横坐标的改变,能力有限,研究了几个小时无果,就改变了方法。将三个图表分别写成年月日三个组件,用一个tab和router-view来实现三个年月日的图表跳转。
具体就是在路由里面设置:
{
path: '/Charts',
name: 'Charts',
component: Charts,
children: [
{
path: '/year',
name: 'year',
component: year
},
{
path: '/',
name: 'year',
component: year
},
{
path: '/month',
name: 'month',
component: month,
},
{
path: '/day',
name: 'day',
component: day,
},
]
},
children的路由设置很关键啊,要记住啊。记得在路由的上面要import各个组件。
然后集成在一个charts的组件里
<div style="margin-top:10px;">
<router-link to="year" class="dianji">year</router-link>
<router-link to="month" class="dianji">month</router-link>
<router-link to="day" class="dianji">day</router-link>
<router-view></router-view>
</div>
第三部,在地图左上角加一个checkbox控件,点击显示各个点。
老板说完我就头晕,在纸上写写画画怎么实现。逻辑这个东西实在是难搞。要先找出地图上的点就是makers与checkbox的关系。
然后如何在checkbox已选中的情况重新标记点。能力实在有限啊,又是想了几个小时,尝试了我的各种想法都没办法实现,老板看我做不出来,就指了跳明路,用路由跳转来实现地图重新加载把。思路一下就清晰了,用一个数组来记录每个点的状态,就是选中还是没选中,选中就在数组里面push相应的数字。例如:选中第2个checkbox就push '1'到数组。通过数组来标出相应的地点,然后将这个数组当作参数来传递到另外一个地图组件,就是在两个地图组件里面来回跳转,来实现每一次地点标注的重新渲染。逻辑在接下来的实现效果的过程中不断完善,真是一种极其良好的coding体验。
一开始是有点蠢的,贪快,把checkbox数据写死了,因为我知道数据里面就四个点,我就写了四个checkbox,每一个check都绑定一个方法,就是push数字到数组里(option),然后,php同事叼我了,说他改了数据之后怎么办,那没办法了,想办法用vue渲染数据里面的地点咯,其实也挺简单的 就是懒:
<div class="check-box">
<template v-for="(item,index) in scope">
<label @change="joinOptions(index,item)" :key="index">
{{item.name}}
<input type="checkbox" id="one" v-model="item.state">
</label>
</template>
然后,想办法将option与makers(地图标点)关联起来,参考之前的循环输出获得的数据来一个一个标记出数据里的点,我就想到了,用两个for循环来相匹配option和makers。就是先for循环出makers,再将makers的索引放入下一个循环,当两个索引相等时,option的数字就跟是第几个makers相等了。
var markers = this.markers;
var point = this.point;
for (var i = 0; i < this.scope.length; i++) {
for (var a = 0; a < this.options.length; a++) {
if (i == this.options[a]) {
var p0 = this.scope[i]["longitude"]; //经度
var p1 = this.scope[i]["latitude"]; // 纬度
this.point[i] = new BMap.Point(p0, p1);
// map.panTo(point[i]);
this.markers[i] = new BMap.Marker(point[i]);
map.addOverlay(markers[i]); // 将标注添加到地图中
map.panTo(point[this.options[0]]);
addClickHandler("驻点名称:" + this.scope[i]["name"], markers[i]); //设置点击响应事件
}
}
}
检验方法就是 要利用console.log打印,这个方法真是太好用了。
因为是跳转,所以是要两个组件。就复制了一个cross组件。然后将option作为路由参数传给cross,Bmap(当前的地图组件)也同样是如此,然后要将接收到的option数据放到当前组件的option里。
路由:
routes: [
{
path: '/',
name: 'Bmap',
component: Bmap,
},
{
path: '/cross',
name: 'cross',
component: cross
},
跳转方法与传参:
methods: {
across: function() {
this.$router.push({ path: "/cross", query: { options: this.options } });
},
获取数据,写在axios里面,因为 map渲染就是在axios获取到数据之后渲染的。
this.options = this.$route.query.options;
this.options = this.options == undefined ? [] : this.options;
第二行代码是什么意思呢,第一个=号是赋值,第二个==号是判断,就是判断this.options是不是等于undefined,等于的话,使this.options=[],就是变成空数组,不等于的话,使this.options等于this.$route.query.options。因为参数传进来之后,this.option是undefind的,应该是跟我胡乱操作data里面的option有关,不应该这样写的,但是我也没想到其他方法,就硬撑着写吧,要靠之后的学习去弥补了。
最后就是如何判断checkbox'的状态来进行数组options的增删了。
<div class="check-box">
<template v-for="(item,index) in scope">
<label @change="joinOptions(index,item)" :key="index">
{{item.name}}
<input type="checkbox" id="one" v-model="item.state">
</label>
</template>
用v-model="item.state"来绑定input的状态
joinOptions: function(index,item) {
if(item.state){
this.options.push(index);
}else{
var index2 = this.options.indexOf(index);
if(index2>-1){
this.options.splice(index2,1);
}
}
// item.state = !item.state;
console.log(this.options);
},
方法的传参比较重要,将index和item都传进来,index就相当于是makes和checkbox的索引了,因为他们是共用一份数据的,就是scope,在creat()里面就把数据拉到scope里了。然后就是判断checkbox的选中状态,来决定是否push参数进去option,或者删除掉已经传入的参数。删除就是通过indexOf来查找option里面是否有等于当前index的值。有的话就删除了。
应该是写得差不多了,之后再把项目传到github上再附上网址吧。