Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
map-demo
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2024-09-14 17:45:07 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
878fc12d43a489d70aece9e7b7c42fb60ded6dfc
878fc12d
1 parent
327b9f6b
✨ feat(新增地图主体页面):
别院甘露
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
693 additions
and
1 deletions
src/route.js
src/views/bieyuan/map.vue
vite.config.js
src/route.js
View file @
878fc12
/*
* @Date: 2023-05-29 11:10:19
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-0
3-21 17:19:1
4
* @LastEditTime: 2024-0
9-14 14:23:5
4
* @FilePath: /map-demo/src/route.js
* @Description: 文件描述
*/
...
...
@@ -41,4 +41,11 @@ export default [
title
:
'工具地图'
,
},
},
{
path
:
'/bieyuan/map'
,
component
:
()
=>
import
(
'@/views/bieyuan/map.vue'
),
meta
:
{
title
:
'地图'
,
},
}
];
...
...
src/views/bieyuan/map.vue
0 → 100644
View file @
878fc12
<!--
* @Date: 2023-05-19 14:54:27
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-09-14 17:35:43
* @FilePath: /map-demo/src/views/bieyuan/map.vue
* @Description: 公众地图主体页面
-->
<template>
<div ref="root" style="height: 100vh; position: relative; overflow: hidden;">
<div id="container"></div>
</div>
</template>
<script>
// import { mapState } from 'vuex'
import coord from '@/common/map_data'
import my_router from '@/common/my_router'
import _ from 'lodash';
import $ from 'jquery';
import { useRect } from '@vant/use';
import { mapAPI } from '@/api/map.js'
import wx from 'weixin-js-sdk'
const GPS = {
PI: 3.14159265358979324,
x_pi: 3.14159265358979324 * 3000.0 / 180.0,
delta: function (lat, lon) {
var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
var dLat = this.transformLat(lon - 105.0, lat - 35.0);
var dLon = this.transformLon(lon - 105.0, lat - 35.0);
var radLat = lat / 180.0 * this.PI;
var magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
return {
'lat': dLat,
'lon': dLon
};
},
//WGS-84 to GCJ-02
gcj_encrypt: function (wgsLat, wgsLon) {
if (this.outOfChina(wgsLat, wgsLon))
return {
'lat': wgsLat,
'lon': wgsLon
};
var d = this.delta(wgsLat, wgsLon);
return {
'lat': wgsLat + d.lat,
'lon': wgsLon + d.lon
};
},
outOfChina: function (lat, lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
},
transformLat: function (x, y) {
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
return ret;
},
transformLon: function (x, y) {
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
return ret;
}
};
export default {
components: { },
data() {
return {
map: '',
geolocation: '',
current_lng: '',
current_lat: '',
dialog_show: false,
dialog_text: '',
location_marker: '',
itemInfo: {},
navBarList: [],
navList: [],
navKey: '',
markerSum: [], // marker合集
mapTiles: [],
data_center: [], // 接口获取-地图中心点
data_zoom: '', // 接口获取-地图默认缩放
data_zooms: '', // 接口获取-地图默认缩放范围
data_rotation: 0, // 接口获取-地图旋转角度
data_paths: {}, // 接口获取-地图导航路径
data_path_list: [], // 接口获取-地图导航路径
}
},
async mounted() {
const code = this.$route.query.id;
const { data } = await mapAPI({ i: code });
this.navBarList = data.list; // 底部导航条
this.mapTiles = data.level; // 获取图层
this.navKey = data.list[0]['id']; // 默认选中 第一个 id
this.navList = data.list.filter(item => item.id === this.navKey)[0]['list']; // 返回默认选中项的实体信息
this.data_center = data.map.center.map(item => Number(item)); // 地图中心点
this.data_zoom = data.map.zoom; // 地图默认缩放
this.data_rotation = data.map.rotation; // 地图旋转角度
this.data_zooms = data.map.zooms.map(item => Number(item)); // 地图默认缩放范围
this.data_paths = data.map.path ? data.map.path : {}; // 地图默认导航路径
if (data.map.path) {
for (const key in data.map.path) {
const element = data.map.path[key];
this.data_path_list.push({
name: key,
path: element,
status: true
})
}
}
// 初始化地图
this.initMap();
// this.setMapBoundary();
// 使用之前获取当前地址,判断当前是否能够获取经纬度
wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: (res) => {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
this.current_lng = GPS.gcj_encrypt(latitude, longitude).lon;
this.current_lat = GPS.gcj_encrypt(latitude, longitude).lat;
},
});
// 设置贴片地图
this.setTitleLayer();
},
watch: {
},
methods: {
initMap() {
// 初始化地图
this.map = new AMap.Map('container', {
viewMode: '2D', // 设置地图模式
turboMode: false,
showIndoorMap: false,
defaultCursor: 'pointer', // 地图默认鼠标样式
showBuildingBlock: false, // 是否展示地图 3D 楼块
zooms: this.data_zooms, // 地图显示的缩放级别范围, 默认为 [2, 20] ,取值范围 [2 ~ 30]
showLabel: true, // 是否展示地图文字和 POI 信息
zoom: this.data_zoom, // 设置地图显示的缩放级别
pitch: 0, // 俯仰角度,默认 0,最大值根据地图当前 zoom 级别不断增大,2D地图下无效 。
rotation: this.data_rotation, // 地图顺时针旋转角度,取值范围 [0-360] ,默认值:0
center: this.data_center, // 设置地图中心点坐标
forceVector: false,
// rotateEnable: true,
layers: [
// new AMap.TileLayer.RoadNet(),
],
features: ['bg', 'road'], // 设置地图上显示的元素种类
animateEnable: false, // 地图平移过程中是否使用动画
resizeEnable: true,
});
// 添加地图点击事件
this.map.on("click", this.showInfoClick);
// 加载景点图层
this.loadMaker(this.navKey);
//
this.map.setRotation(this.data_rotation, true);
},
loadMaker(id) {
var zoomStyleMapping = { 14: 0, 15: 0, 16: 0, 17: 0, 18: 0, 19: 0, 20: 0 };
const entity_info = this.navBarList.filter(item => item.id === id)[0]['list'];
this.markerSum = [];
_.each(entity_info, (x, i) => {
let marker_icon = '';
if (entity_info[i].window_type === 'warn' && entity_info[i].details.length === 1) { // 如果是预警类型并且内部预警项目只有一个取details第一个icon
marker_icon = entity_info[i].details[0]['icon'];
} else {
marker_icon = entity_info[i].icon;
}
if (entity_info[i]?.writing_mode === 'vertical') { // 标题文字垂直
var textMarker = new AMap.Text({
zooms: [18, 20], // 点标记显示的层级范围,超过范围不显示。
text: entity_info[i].name, //标记显示的文本内容
anchor: "center", //设置文本标记锚点位置
// draggable: true, //是否可拖拽
// cursor: "pointer", //指定鼠标悬停时的鼠标样式。
// angle: 10, //点标记的旋转角度
style: {
//设置文本样式,Object 同 css 样式表
"padding": ".5rem .2rem .5rem .2rem",
// "margin-bottom": "1rem",
// "border-radius": ".25rem",
"background-color": "#965f13",
// "width": "1rem",
// "border-width": 0,
// "box-shadow": "0 2px 6px 0 rgba(114, 124, 245, .5)",
// "text-align": "center",
"font-size": "0.8rem",
"color": "white",
"writing-mode": "vertical-rl",
"text-orientation": "mixed",
"display": "flex",
"justify-content": "center",
"align-items": "center",
},
position: entity_info[i].position, //点标记在地图上显示的位置
});
if (clickListener1) {
textMarker.off('click', clickListener)
}
// 绑定景点的点击事件 - 文字出现才能触发
var clickListener1 = textMarker.on('click', (e) => {
// console.warn(e);
this.itemInfo = entity_info[i];
// 不同弹框类型
// if (entity_info[i].window_type === 'normal') {
// this.showInfoPopup = true;
// } else if (entity_info[i].window_type === 'lite') {
// this.showInfoLitePopup = true;
// } else if (entity_info[i].window_type === 'warn') {
// this.showInfoWarnPopup = true;
// }
// 修改文本的样式
textMarker.setStyle({
'font-size': '20px', // 修改字体大小
'color': '#ff0000', // 修改字体颜色
'background-color': '#0000ff', // 修改背景颜色
'border': '1px solid #fff', // 增加边框
'padding': '10px', // 调整内边距
'border-radius': '10px' // 调整圆角
});
// 修改文本内容
textMarker.setText('样式已修改');
})
textMarker.setMap(this.map); //将文本标记设置到地图上
this.markerSum.push(textMarker);
}
})
this.map.add(this.markerSum);
},
isPointInRing() { // 是否在景区范围
let isPointInRing = AMap.GeometryUtil.isPointInRing([this.current_lng, this.current_lat], [
[120.585111, 31.316084], [120.585111, 31.316084], [120.589488, 31.313197], [120.585422, 31.313005]
]);
return isPointInRing
},
setLocation() { // 开启定位服务
// 获取失败
if (!this.current_lng || !this.current_lat) {
this.dialog_show = true;
this.dialog_text = '获取经纬度失败';
}
this.getLocation();
// // this.map.addControl(this.geolocation); // 添加定位图标 自动跳转当前位置
// if (!this.current_lng || !this.current_lat) {
// this.getLocation()
// } else {
// // 判断是否在范围内
// if (!this.isPointInRing()) {
// this.dialog_show = true;
// this.dialog_text = '您不在景区范围内';
// } else {
// // this.current_lng = '120.587643'
// // this.current_lat = '31.314853'
// // 使用纠正偏移后的地址,打一个定位标记
// this.location_marker = new AMap.LabelMarker({
// icon: {
// image: 'https://cdn.ipadbiz.cn/xys/map/%E5%AE%9A.png',
// anchor: 'bottom-center',
// size: [36, 36],
// },
// position: new AMap.LngLat(this.current_lng, this.current_lat), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
// });
// this.map.add(this.location_marker);
// // 定位到当前位置中心
// this.map.setZoomAndCenter(this.zoom, [this.current_lng, this.current_lat]);
// }
// }
},
getLocation() { // 获取经纬度
// PC端无法获取定位
// 微信获取地址
wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: (res) => {
var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
var speed = res.speed; // 速度,以米/每秒计
var accuracy = res.accuracy; // 位置精度
this.current_lng = GPS.gcj_encrypt(latitude, longitude).lon;
this.current_lat = GPS.gcj_encrypt(latitude, longitude).lat;
// 判断是否在范围内
if (!this.isPointInRing()) {
this.dialog_show = true;
this.dialog_text = '您不在景区范围内';
} else {
// 使用纠正偏移后的地址,打一个定位标记
this.location_marker = new AMap.LabelMarker({
icon: {
image: 'https://cdn.ipadbiz.cn/xys/map/%E5%AE%9A.png',
anchor: 'bottom-center',
size: [36, 36],
},
position: new AMap.LngLat(this.current_lng, this.current_lat), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
});
this.map.add(this.location_marker);
// 定位到当前位置中心
this.map.setZoomAndCenter(this.zoom, [this.current_lng, this.current_lat]);
}
},
complete: () => {
// 获取失败
if (!this.current_lng || !this.current_lat) {
this.dialog_show = true;
this.dialog_text = '获取经纬度失败';
}
},
});
},
setZoom(type) { // 设置放大缩小地图
const zoom = this.map.getZoom();
if (type === 'plus') {
this.map.setZoom(zoom + 1)
}
if (type === 'minus') {
this.map.setZoom(zoom - 1)
}
},
computedMapSource(x, y, z) { // 根据图层信息生成图层实际地址
for (const id in this.mapTiles) {
if (z == id) {
const scope = this.mapTiles[id];
return scope[`${x}-${y}`]
}
}
},
setTitleLayer() { // 生成瓦片图
// 获取瓦片图渲染范围
function getFirstProperty(obj) {
for (var prop in obj) {
return prop;
}
}
function getLastProperty(obj) {
var props = [];
for (var prop in obj) {
props.push(prop);
}
return props[props.length - 1];
}
let obj_scope = {};
for (const key in this.mapTiles) {
const element = this.mapTiles[key];
let first = getFirstProperty(element).split('-');
let last = getLastProperty(element).split('-');
obj_scope[key] = {
x: [first[0], last[0]],
y: [first[1], last[1]]
}
}
const _this = this;
var layer = new AMap.TileLayer.Flexible({
cacheSize: 50,
opacity: 1,
zIndex: 100,
createTile: function (x, y, z, success, fail) {
// 控制地图等级显示图片范围-过滤不显示的图层渲染
for (const id in obj_scope) {
if (z == id) {
const scope = obj_scope[id];
if (x < scope.x[0] || x > scope.x[1]) {
fail()
return;
}
if (y < scope.y[0] || y > scope.y[1]) {
fail()
return;
}
}
}
var img = document.createElement('img');
img.onload = function () {
success(img)
};
img.crossOrigin = "anonymous";// 必须添加,同时图片要有跨域头
img.onerror = function () {
fail()
};
// img.src = `images/tiles/${z}/${x}_${y}.png`;
img.src = _this.computedMapSource(x, y, z);
},
});
this.map.addLayer(layer);
// Canvas作为切片
var layer1 = new AMap.TileLayer.Flexible({
// tileSize: 128,
cacheSize: 300,
zIndex: 200,
createTile: function (x, y, z, success, fail) {
var c = document.createElement('canvas');
c.width = c.height = 256;
var cxt = c.getContext("2d");
cxt.font = "15px Verdana";
cxt.fillStyle = "#ff0000";
cxt.strokeStyle = "#FF0000";
cxt.strokeRect(0, 0, 256, 256);
cxt.fillText('(' + [x, y, z].join(',') + ')', 10, 30);
// 通知API切片创建完成
success(c);
}
});
// layer1.setMap(this.map);
// TODO: 暂时屏蔽等待数据设置字段
// 只显示相应区域,移动会回到选定范围
const id = this.$route.query.id;
if (id === '1759271') { // 定制开发
this.lockMapBounds()
}
},
// 限制地图范围
lockMapBounds() {
// var bounds = this.map.getBounds();
var myBounds = new AMap.Bounds(
[117.045587,26.838764],
[117.051081,26.8345723]
);
this.map.setLimitBounds(myBounds);
let list =[
[117.045598,26.838764],
[117.051075,26.838779],
[117.051075,26.835107],
[117.045598,26.835107]
]
// 隐藏边界以外的区域
let outer = [
new AMap.LngLat(-360, 90, true),
new AMap.LngLat(-360, -90, true),
new AMap.LngLat(360, -90, true),
new AMap.LngLat(360, 90, true),
] // 遮盖填充反向
let pathArray = [
outer,
list
]
var polygon = new AMap.Polygon({
pathL: pathArray,
strokeColor: "#fff",
strokeWeight: 2,
fillColor: "#fff",
fillOpacity: 1,
})
polygon.setPath(pathArray)
this.map.add(polygon)
},
showInfoClick(e) {
// console.log(e);
var zoom = this.map.getZoom(); //获取当前地图级别
// var text =
// "您在 [" +
// e.lnglat.getLng() +
// "," +
// e.lnglat.getLat() +
// "] 的位置单击了地图!当前层级" +
// zoom;
var text =
"[" +
e.lnglat.getLng() +
"," +
e.lnglat.getLat() +
"],"
console.log(text);
},
}
}
</script>
<style lang="less">
#container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
// 遮挡地图logo
.amap-logo {
display: none!important;
visibility: hidden!important;
}
.amap-copyright {
display: none!important;
visibility: hidden!important;
}
/* 标记文字样式 */
.amap-marker-label {
padding: 0.25rem 0.5rem;
width: auto;
border: none;
border-radius: 2px;
background: rgba(86, 65, 23, 0.8);
color: white;
}
.amap-marker {
.amap-icon {
margin-top: 0.25rem;
}
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border-radius: .25rem;
width: 20rem;
border-width: 0;
border-radius: 0.4rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
position: fixed;
top: 4rem;
right: 1rem;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0.75rem 1.25rem;
}
.tool-bar-wrapper {
position: absolute;
left: 20px;
bottom: 8rem;
width: 20px;
}
.nav-bar-wrapper {
position: fixed;
bottom: 0;
left: 0;
height: 5.5rem;
width: 100%;
background-color: white;
text-align: center;
box-shadow: 0 -1px 0 rgba(80, 80, 80, 0.1);
z-index: 999;
// padding: 0.5rem 0;
padding-bottom: 0.5rem;
.nav-bar-content {
display: flex;
overflow-x: scroll;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
position: relative;
}
.item {
padding-top: 0.5rem;
color: #888;
width: 21.5%;
flex-shrink: 0;
padding-top: 1rem;
}
.checked {
color: #965f13;
}
}
.safe-route-wrapper {
position: absolute;
bottom: 2rem;
right: 1rem;
background-color: white;
}
.operate-bar-wrapper {
position: fixed;
left: 20px;
bottom: 6rem;
width: 20px;
height: auto;
z-index: 100;
.box-wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.item {
position: relative;
text-align: center;
font-size: 0.85rem;
width: 2rem;
height: 2rem;
background-color: white;
margin-bottom: 1rem;
border-radius: 50%;
padding: 2.5px;
line-height: 2rem;
}
}
}
.popup-wrapper {
margin-top: 1rem;
.title {
font-size: 1.25rem;
margin-bottom: 0.85rem;
}
.content {
line-height: 1.75;
font-size: 0.95rem;
}
}
.hideScrollBar::-webkit-scrollbar {
display: none;
}
.hideScrollBar {
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
}
.van-dialog__confirm,
.van-dialog__confirm:active {
color: #AB8F57;
}
.walk-nav-text {
position: fixed;
bottom: 6rem;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999;
background: rgba(86, 65, 23, 0.8);
color: white;
border-radius: 10px;
padding: 5px 12px;
font-size: 0.8rem;
}
</style>
vite.config.js
View file @
878fc12
...
...
@@ -153,6 +153,12 @@ export default ({ command, mode }) => {
// mono1: path.resolve(__dirname, 'src/packages/mono1/index.html'),
// mono2: path.resolve(__dirname, 'src/packages/mono2/index.html'),
},
manualChunks
(
id
)
{
if
(
id
.
includes
(
'node_modules'
))
{
return
id
.
toString
().
split
(
'node_modules/'
)[
1
].
split
(
'/'
)[
0
].
toString
();
// return 'vendor';
}
}
},
},
optimizeDeps
:
{
...
...
Please
register
or
login
to post a comment