2、设定打卡半径(圆形电子围栏)
3、时时获取定位
4、计算定位到公司的直线距离
5、对比 打卡半径>直线距离,打卡成功

DEMO:

v-show="mapShow"
ref="VeBmapRef"
:settings="chartSettings"
:series="chartSeries"
:tooltip="chartTooltip"
:after-set-option-once="afterSet"
>
打卡
{{thisTime}}
未到达
考勤范围
{{thisTime}}
每{{frequency/1000}}秒更新一次定位,目前更新{{mark}}次
import Vue from "vue";
import context from "@/components/form/context";
import VeBmap from "v-charts/lib/bmap.common";
import { fmtTime } from "@/utils";
export default {
components: {
VeBmap,
},
data() {
this.chartSettings = {
key:"申请的百度地图key",
bmap: {
// 百度地图中心经纬度
// center: [116.396428,39.917614],
// 百度地图缩放
zoom: 19,
// 是否开启拖拽缩放,可以只设置 'scale' 或者 'move'
roam: true,
// 百度地图的自定义样式,见 http://developer.baidu.com/map/jsdevelop-11.htm
mapStyle: {},
},
};
this.chartTooltip = { show: true };
return {
addressPoint: "118.051301,24.619201",
addressRadius: "500",
//
mapShow: false,
map: null, //百度地图实例对象
zoom: 16,
markOverlays: [],
myPoint: { lng: 0, lat: 0 },
distance: 9999,
chartSeries: [
{
type: "scatter",
// 使用百度地图坐标系
coordinateSystem: "bmap",
// 数据格式跟在 geo 坐标系上一样,每一项都是 [经度,纬度,数值大小,其它维度...]
// data: [[120, 30, 1]],
},
],
thisTime: "23:59:59",
thisTimer: null,
frequency: 10000,
mark: 0,
};
},
computed: {
companyPoint() {
let _j = { lng: "", lat: "" };
if (
typeof this.addressPoint == "string" &&
this.addressPoint.indexOf(",") > 0
) {
let ar = this.addressPoint.split(",");
_j.lng = ar[0] || 0;
_j.lat = ar[1] || 0;
}
return _j;
},
},
watch: {},
created() {
this.updateTitle(this.$route.meta.title);
this.addressPoint =
localStorage.getItem("addressPoint") || this.addressPoint;
this.addressRadius =
localStorage.getItem("addressRadius") || this.addressRadius;
this.thisTimer = setInterval(() => {
this.thisTime = fmtTime("HH:MM:SS", new Date());
}, 1000);
},
destroyed() {
clearInterval(this.thisTimer);
},
methods: {
...mapMutations({
updateTitle: types.UPDATE_TITLE,
}),
toSignFu(){
this.$dialog.alert({
title: "打卡成功",
message:this.thisTime
});
},
afterSet(echarts) {
let that = this;
// 获取百度地图实例
let map = echarts.getModel().getComponent("bmap").getBMap();
this.map = map;
// 使用百度地图自带的控件
map.addControl(new window.BMap.MapTypeControl());
// 初始化地图,设置中心点坐标和地图级别
console.log(this.companyPoint);
this.map.centerAndZoom(
new window.BMap.Point(this.companyPoint.lng, this.companyPoint.lat),
that.zoom
);
this.markCircle(this.companyPoint, this.addressRadius);
this.getCurrentPosition();
// 添加定位控件
var geoCtrl = new BMap.GeolocationControl({
showAddressBar: true, //是否显示
enableAutoLocation: false, //首次是否进行自动定位
offset: new BMap.Size(0, 25),
//, locationIcon : icon //定位的icon图标
});
//监听定位成功事件
geoCtrl.addEventListener("locationSuccess", function (r) {
console.log(r);
that.myPoint = r.point;
that.markPoint(r.point, "当前", true);
// that.getAddress();
// that.address.searchList = [];
});
//监听定位失败事件
geoCtrl.addEventListener("locationError", function (e) {
console.log(e);
});
// 将定位控件添加到地图
map.addControl(geoCtrl);
},
clearAllOverlays() {
// 百度地图API功能
let map = this.map;
this.markOverlays.forEach((overlay) => {
map.removeOverlay(overlay);
});
},
markPoint(point, label = "", go = false, doClear = true) {
// 百度地图API功能
let map = this.map;
if (doClear) {
this.clearAllOverlays();
}
var overlay = new BMap.Marker(point);
if (label) overlay.setLabel(this.getLabel(label));
map.addOverlay(overlay);
this.markOverlays.push(overlay);
if (go) {
this.toPoint(point);
}
},
/**
* 画圆
* point 圆心 经纬度
* radius 半径,单位/米
*/
markCircle(point, radius) {
console.log(point);
// 百度地图API功能
let map = this.map;
//创建圆对象
let circle = new BMap.Circle(point, radius, {
strokeColor: "blue",
strokeWeight: 1,
fillColor: "#E2E8F1",
fillOpacity: 0.6,
});
console.log(circle);
//画到地图上面
map.addOverlay(circle);
console.log(circle.getRadius());
},
markLine(points) {
let num = points.length;
let pointObjs = [];
for (let i = 0; i < num; i++) {
let point = points[i];
pointObjs.push(new BMap.Point(point.lng, point.lat));
}
// 百度地图API功能
let map = this.map;
var polyline = new BMap.Polyline(pointObjs, {
strokeColor: "blue",
strokeWeight: 2,
strokeOpacity: 0.5,
});
map.addOverlay(polyline);
this.distance = map.getDistance(pointObjs[0], pointObjs[1]);
},
getLabel(content) {
let fontSize = 12;
let len = content.length * fontSize;
//左偏移 右偏移
var labelStyle = {
color: "#fff",
backgroundColor: "#333333",
border: "0",
fontSize: fontSize + "px",
width: len + "px",
opacity: "0.8",
textAlign: "center",
verticalAlign: "center",
borderRadius: "2px",
whiteSpace: "normal",
wordWrap: "break-word",
padding: "2px 4px",
};
//用于设置样式
var spanA = "";
//不同数字长度需要设置不同的样式。
var offsetSize = new BMap.Size(-len / 2, -25);
var label = new BMap.Label(content + spanA, {
offset: offsetSize,
});
label.setStyle(labelStyle);
return label;
},
toPoint(point) {
// 百度地图API功能
let map = this.map;
map.panTo(point);
},
getCurrentPosition() {
let that = this;
// 百度地图API功能
let map = this.map;
let BMap = window.BMap;
let geolocation = new BMap.Geolocation();
that.currentValue = "";
that.placeholder = "定位中";
geolocation.getCurrentPosition(
function (r) {
if (this.getStatus() == BMAP_STATUS_SUCCESS) {
that.myPoint = r.point;
that.markPoint(r.point, "当前", true);
that.markLine([r.point, that.companyPoint]);
that.mark++;
if (that.frequency > 0) {
setTimeout(() => {
that.getCurrentPosition();
}, that.frequency);
}
} else {
that.$toast("failed" + this.getStatus());
}
},
{ enableHighAccuracy: true }
);
//关于状态码
//BMAP_STATUS_SUCCESS 检索成功。对应数值“0”。
//BMAP_STATUS_CITY_LIST 城市列表。对应数值“1”。
//BMAP_STATUS_UNKNOWN_LOCATION 位置结果未知。对应数值“2”。
//BMAP_STATUS_UNKNOWN_ROUTE 导航结果未知。对应数值“3”。
//BMAP_STATUS_INVALID_KEY 非法密钥。对应数值“4”。
//BMAP_STATUS_INVALID_REQUEST 非法请求。对应数值“5”。
//BMAP_STATUS_PERMISSION_DENIED 没有权限。对应数值“6”。(自 1.1 新增)
//BMAP_STATUS_SERVICE_UNAVAILABLE 服务不可用。对应数值“7”。(自 1.1 新增)
//BMAP_STATUS_TIMEOUT 超时。对应数值“8”。(自 1.1 新增)
},
},
};
.tips {
text-align: center;
font-size: 10px;
color: #333;
}
.sign-btn-box {
width: 2rem;
height: 2rem;
margin: 0.5rem auto;
background: yellowgreen;
background-image: radial-gradient(circle, yellowgreen, rgb(156, 206, 57), rgb(98, 131, 33));
border-radius: 50%;
.sign-btn-title {
font-size: 0.5rem;
font-weight: bold;
color: white;
}
.small {
font-size: 0.25rem;
}
.sign-btn-time {
font-size: 0.3rem;
color: white;
}
}
.sign-btn-box.not-ready {
background: red;
background-image: radial-gradient(circle, red, #f43030, #7d4242);
}