福田做网站优化乐云seo,淄博网站制作服务,线上设计师做效果图,wordpress用户注册密码需求及效果
原本项目使用的是百度地图3.0,也就是2d版本的那个地图#xff0c;客户不满意觉得不够好看#xff0c;让把地图改成3d的#xff0c;但是我们因为另外的系统用的都是百度地图#xff0c;为了保持统一只能用百度地图做
经过3天的努力#xff0c;最后我终于把这个…需求及效果
原本项目使用的是百度地图3.0,也就是2d版本的那个地图客户不满意觉得不够好看让把地图改成3d的但是我们因为另外的系统用的都是百度地图为了保持统一只能用百度地图做
经过3天的努力最后我终于把这个效果实现了效果如下
如何引用GL版本
为了实现这个功能首先要将百度地图升级为GL版本。
GL版本引用的百度地图API需将之前引入的替换为
script typetext/javascript srchttps://api.map.baidu.com/api?v1.0typewebglak您的密钥/script初始化地图
地图初始化还是和之前一样只不过要使用BMapGL const map new BMapGL.Map(monitorMap); // 创建地图实例var point new BMapGL.Point( 128.2015353412464,49.76416045410938); // 创建点坐标map.centerAndZoom(point, 7); // 设置地图中心点map.enableScrollWheelZoom(true); // 允许鼠标滚动缩放地图级别将底图改为卫星地图
GL版本的百度地图有三种地图类型
地球模式BMAP_EARTH_MAP不过这个模式能支持的交互操作有限标准地图BMAP_NORMAL_MAP卫星地图BMAP_SATELLITE_MAP
因此我们给地图加上配置
const map new BMapGL.Map(monitorMap,{mapType:BMAP_SATELLITE_MAP,
}); 禁用地图旋转禁止技改变倾角
这个地图我们不能让用户自己去改变旋转角和倾角因此需要禁用
const map new BMapGL.Map(monitorMap,{mapType:BMAP_SATELLITE_MAP,// 禁用用户旋转enableRotate: false,// 禁用用户修改倾斜角度enableTilt: false,
}); 代码修改地图倾角
做了这么多发现地图依然不是三维的
不要慌我们手动来改一下地图倾角
map.setTilt(50); //设置地图的倾斜角度现在地图终于倾斜了
掩膜以及掩膜经常失败怎么解决
由于我们的效果只需要留下黑龙江省的地图所以需要区域掩膜
我们需要获取黑龙江的边界在百度地图中有对应API
var bdary new BMapGL.Boundary();
bdary.get(黑龙江, function (rs) {// 绘制行政区for (var i 0; i rs.boundaries.length; i) {var path [];var xyArr rs.boundaries[i].split(;);var ptArr [];for (var j 0; j xyArr.length; j) {var tmp xyArr[j].split(,);var pt new BMapGL.Point(tmp[0], tmp[1]);ptArr.push(pt);}// 添加掩膜var mapmask new BMapGL.MapMask(ptArr, {isBuildingMask: true,isPoiMask: true,isMapMask: true,showRegion: inside,});map.addOverlay(mapmask);// 给掩膜描边var border new BMapGL.Polyline(ptArr, {strokeColor: #15a6db,strokeWeight: 3,strokeOpacity: 1});map.addOverlay(border);}
})现在终于把黑龙江单独拎出来了但为什么背景是白色的这个先不急我们先来解决另一个问题
区域掩膜失败怎么解决
多刷新几次页面你会发现有时候区域掩膜会失败为什么呢
我们分析一下为什么有时失败有时不失败这是不是非常像接口请求有时成功有时失败的样子实际上百度地图也是这样做的是因为黑龙江的边界请求有时候会失败
解决思路 黑龙江的边界不会变的我们把请求成功的黑龙江边界存起来就行了
// heilongjiang.js
export default {boundaries: [121.50682596458674, 53.341380780914506;121.51059812908427, 53.34188131383469;121.51345447111437, 53.34197641979837;121.51517077362173, 53.34203018226125;.....]
}然后将代码修改一下
import heilongjiang from ./heilongjiang.js;for (var i 0; i heilongjiang.boundaries.length; i) {var path [];var xyArr heilongjiang.boundaries[i].split(;);var ptArr [];for (var j 0; j xyArr.length; j) {var tmp xyArr[j].split(,);var pt new BMapGL.Point(tmp[0], tmp[1]);ptArr.push(pt);}var mapmask new BMapGL.MapMask(ptArr, {isBuildingMask: true,isPoiMask: true,isMapMask: true,showRegion: inside,});map.addOverlay(mapmask);// 给地图描边不需要描边可以去掉var border new BMapGL.Polyline(ptArr, {strokeColor: #15a6db,strokeWeight: 3,strokeOpacity: 1});map.addOverlay(border);}怎么让背景变透明
我们在初始化地图的时候加上配置 const map new BMapGL.Map(monitorMap, {enableRotate: false,enableTilt: false,mapType:BMAP_SATELLITE_MAP,backgroundColor: [0, 0, 0, 0],}); 然后设置css样式
#monitorMap {background: none!important;
}现在背景变透明了我在地图下方加上了自己的背景图
顶上的天空渐变怎么去掉
细心的同学会发现地图顶上有白色的天空渐变我们并不想要它加一个配置去掉它
map.setDisplayOptions({skyColors: [rgba(186, 0, 255, 0),rgba(186, 0, 255, 0)]
})将天空渐变色的透明度都改为0就可以去掉了
怎么给地图增加厚度
不想要有厚度的地图到这一步就可以结束了后面该干嘛干嘛但是呢我喜欢折腾试过很多种方法都不行最终我使用了百度的三维模型图层这一步需要有一点threejs的基础不过没有也没关系跟着我往下走就是了
引入依赖
在百度api后面追加几个script
script typetext/javascriptsrchttps://api.map.baidu.com/api?typewebglv1.0ak您的密钥/script
!--引入样式--
script typetext/javascript srchttps://mapv.baidu.com/gl/examples/static/common.js/script
script typetext/javascript srchttps://mapopen-pub-jsapigl.bj.bcebos.com/newThree/three.min.js/scriptscript typetext/javascript srchttps://code.bdstatic.com/npm/mapvgl1.0.0-beta.151/dist/mapvgl.min.js/script
script typetext/javascript srchttps://code.bdstatic.com/npm//mapvgl1.0.0-beta.151/dist/mapvgl.threelayers.min.js/script修改地图初始化配置
const map new BMapGL.Map(monitorMap, {forceRenderType: webgl,coordsType: 5, // coordsType指定输入输出的坐标类型3为gcj02坐标5为bd0ll坐标默认为5。enableRotate: false,enableTilt: false,mapType:BMAP_SATELLITE_MAP,backgroundColor: [192, 214, 213, 0],});初始化三维图层
var view new mapvgl.View({map: map
});threeLayer new mapvgl.ThreeLayer({ notUpdateSize: false });
view.addLayer(threeLayer);这里的threeLayer就相当于threejs中的scene了后面的代码和在threejs里写差不多
添加灯光
var lights [];
// 创建点光源
lights[0] new THREE.PointLight(0xffffff, 1, 0);
// 给点光源设置位置
lights[0].position.set(0, -1000, 1000);
// 将光源添加到场景中
threeLayer.scene.add(lights[0]);使用threejs的挤出几何体 ExtrudeGeometry 实现黑龙江省的厚度
根据黑龙江省的边界创建挤出几何体mesh,该几何体的高度为46000因此将该几何体下移46001让该几何体位于地图的下方。
const shape new THREE.Shape()for (var i 0; i heilongjiang.boundaries.length; i) {var xyArr heilongjiang.boundaries[i].split(;);for (var j 0; j xyArr.length; j) {var tmp xyArr[j].split(,);// 将经纬度坐标转换为平面坐标var pt map.lnglatToMercator(tmp[0], tmp[1]);if(j 0) {shape.moveTo( pt[0], pt[1] );}else{shape.lineTo( pt[0], pt[1] );}}}const extrudeSettings {steps: 2,depth: 46000};// 创建挤出几何体的geometryconst geometry1 new THREE.ExtrudeGeometry( shape, extrudeSettings );// 创建挤出几何体的材质const material1 new THREE.MeshLambertMaterial( { color: 0x15a6db, transparent:true,opacity:0.5 } );// 创建地图厚度meshconst mesh new THREE.Mesh( geometry1, material1 ) ;// 修改mesh的位置mesh.position.z -46001// 将mesh添加到threeLayer中去threeLayer.add( mesh );创建三维图层的动画循环
写过threejs的同学都知道threejs绘制物体是需要有动画循环的动画循环中更新画面
function animate() {requestAnimationFrame(animate);threeLayer.update();
}
requestAnimationFrame(animate);现在我们的地图有厚度了如果想要更厚可以多挤出一点距离
其实这里是有些问题的你会发现卫星地图也变蓝一些了这是因为三维模型图层在地图图层的上方我还没有找到解决这个的办法因此将模型的透明度调整为了0.5结果还挺好看的就算了吧
地图缩小总是自动修改倾角怎么解决 现在用鼠标滚轮缩放一下地图哎哎百度地图怎么自动给我修改了倾斜角
然后我翻遍了api文档和demo都没有找到怎么调整这个参数
过程就不说了我看了百度地图api的代码找了很久最终才实现现在来说一下解决方案 用浏览器打开 https://api.map.baidu.com/api?typewebglv1.0ak您的密钥 秘钥要填自己的哦打开是下面的样子 然后用浏览器打开红框圈中的地址将这个js文件下载到本地引入到项目中 打开刚刚的js文件,全局搜索 _enableTiltZoom 找到这一行 将其修改为 this._enableTiltZoom 1;然后限制一下地图最小的缩放尺寸
const map new BMapGL.Map(monitorMap, {forceRenderType: webgl,coordsType: 5, // coordsType指定输入输出的坐标类型3为gcj02坐标5为bd0ll坐标默认为5。enableRotate: false,enableTilt: false,mapType:BMAP_SATELLITE_MAP,backgroundColor: [192, 214, 213, 0],minZoom: 5});好了现在无论怎么缩放都不会修改倾斜角了
如何在地图上布三维点
如何在地图上布点呢一般的点百度地图都有demo这里我就不说了
大家都知道百度地图的marker在超过两百个以后会巨卡之前我也写过2d版本的百度地图海量点方案这里我写一下3d版本的
我这里会准备一个变量存储点的坐标数组然后遍历数组往threeLayer中添加 Cone 当做点位
const pointList [] // 存储三维点对象后面射线拾取的时候要用
let pointWidth 10000 // 三维点的基础宽度
let pointHeight 50000 // 三维点的基础高度
let pointZ 25000 // 三维点的z轴位置// 颜色数组根据不同的status状态画不同颜色的点
const colorList [0xEAEAEA, 0x1CE945, 0xEDE11C, 0xE9860D, 0xF0323F]
// 测试数据
const bridgeListData [{bridgeName: 测试1latitude:47.07133734521393,longitude:129.09809887846538},{bridgeName: 测试2latitude:45.7550708,longitude:126.4918776}
]for(let i 0;ibridgeListData.length;i) {const {longitude, latitude, bridgeName, status} bridgeListData[i]let color colorList[status 1]const geometry new THREE.ConeGeometry( pointWidth, pointHeight, 3 );const material new THREE.MeshLambertMaterial( {color: color} );const cone new THREE.Mesh( geometry, material );// 将经纬度转换为平面坐标const point map.lnglatToMercator(longitude,latitude)// 设置点的空间位置cone.position.x point[0];cone.position.y point[1];cone.position.z pointZ;// 将点旋转270度让锥形的尖头朝下cone.rotateX(270 / 180 * Math.PI);// 将数据存储到点对象上cone.data bridgeListData[i]pointList.push(cone)threeLayer.add(cone);}这样点是加上去了但是缩放地图之后点会变得巨大
三维点如何保持匀称的大小
如何保持点的大小在视觉上不变呢
其实我也没有做到完全不变让大小完全不变的那个公式我暂时还没有摸索出来
原理其实就是在地图缩放的时候将点的尺寸根据地图当前的zoom属性做一下修改就好了
const pointList []
let pointWidth 10000
let pointHeight 50000
let pointZ 25000const colorList [0xEAEAEA, 0x1CE945, 0xEDE11C, 0xE9860D, 0xF0323F]
const bridgeListData [{bridgeName: 测试1latitude:47.07133734521393,longitude:129.09809887846538},{bridgeName: 测试2latitude:45.7550708,longitude:126.4918776}
]// 根据地图的层级返回不同的scale值
function getScale(level) {if(level 1 level 10) {return (15 - level)/level}else if(level 10 level 12){return (13 - level)/level}else if(level 12 level 14) {return 1/(level * (level - 11))}else if(level 14 level 16) {return 1/(level * (level - 11) * 2)}else if(level 16 level 18) {return 1/(level * (level - 11) * 3)}else if(level 18) {return 1/(level * (level - 11) * 4)}return 1/level
}const level map.getZoom()
const scale getScale(level)// 绘制点
for(let i 0;ibridgeListData.value.length;i) {const {longitude, latitude, bridgeName, status, bridgeUniqueCode} bridgeListData.value[i]let color colorList[status 1]const geometry new THREE.ConeGeometry( pointWidth, pointHeight, 3 );const material new THREE.MeshLambertMaterial( {color: color} );const cone new THREE.Mesh( geometry, material );// 缩放点的大小cone.scale.x scalecone.scale.y scalecone.scale.z scaleconst point map.lnglatToMercator(longitude,latitude)cone.position.x point[0];cone.position.y point[1];// 点的z坐标也要缩放cone.position.z pointZ * scale;cone.rotateX(270 / 180 * Math.PI);cone.data bridgeListData.value[i]pointList.push(cone)threeLayer.add(cone);
}// 地图缩放层级的时候更改点的大小
map.addEventListener(zoomend, function(e) {const level map.getZoom()const scale getScale(level)pointList.forEach(cone {cone.scale.x scalecone.scale.y scalecone.scale.z scalecone.position.z pointZ*scale})});三维点的点击事件
然后就可以给三维点添加点击事件了这里我在map的click事件中使用raycaster射线法进行拾取
var raycaster new THREE.Raycaster();
var mouse new THREE.Vector2();// 获取地图的宽高
const size map.getSize()
const canvasWidth size.width
const canvasHeight size.heightmap.addEventListener(mousedown, function (e) {var fs [...pointList]// 归一化鼠标位置范围-1 1,原点在中心mouse.x (e.offsetX / canvasWidth) * 2 - 1;mouse.y -(e.offsetY / canvasHeight) * 2 1;raycaster.setFromCamera(mouse, threeLayer.camera);if (fs.length0) {// 射线检测的对象为三维点var intersects raycaster.intersectObjects(fs);console.log(intersects)}
});这里注意归一化的时候一定要用地图本身的宽高而不是整个屏幕的宽高不然射线拾取会有问题的
好啦到这里效果就和我开头的一样啦只是少了弹窗的部分弹窗我是用html写的和这次的主题关系不大~