Answers
kojima
answered 9 years, 5 months ago
我自己实现了一下,可以自己在百度地图上随便画图形,基本原理就是,监听touch事件,touchMove,保存当前的经纬度,转化为pixel坐标,重复绘制线段,当touchEnd时,绘制矩形图形。最后会连接首位2点,并判断矩形是否有效,同时如果在画得过程中已经有闭合图形,则终止画图。
演示地址,需要使用手机浏览测试:
JS 实现代码:
var app = app || {};
app.BM = {
map: false,
init: function() {
// 百度地图API功能
this.map = new BMap.Map("allmap"); // 创建Map实例
this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 11); // 初始化地图,设置中心点坐标和地图级别
this.map.addControl(new BMap.MapTypeControl()); //添加地图类型控件
this.map.setCurrentCity("北京"); // 设置地图显示的城市 此项是必须设置的
this.map.enableScrollWheelZoom(); //开启鼠标滚轮缩放
this.map.enableDragging();
}
};
// 电子围栏
// @todo 数据交互部分
app.Fence = {
cache_points: [], // 缓存折线数据,取消操作时,重新画图。
polyline:false, // 百度折线覆盖物
points: [], // 折线数据 [H,H,H,...] H{lat:"",lng:""}
coordinate: [], // 像素数据 [P,P,...] P{x:"",y:""}
cur_point: false,
cur_pixel: false,
isOver: false, // 围栏是否已经完成
cross_at: false, // 相交的点索引
state: 0, // 界面状态 0 待设定状态, 1 开始设定, 2 设定完成
polygon: false, // 完成后的栏栅覆盖物
polylineOption: {strokeColor:"blue", strokeWeight:4, strokeOpacity:0.5},
init: function() {
app.BM.init();
this.initClickEvent();
},
initClickEvent: function() {
// 设定或取消
document.getElementById('action').addEventListener('click', this.clickSettingHandler, false);
// 确定或重新设定事件监听
document.getElementById('setok').addEventListener('click', this.setOKHandler, false);
document.getElementById('reset').addEventListener('click', this.resetHandler, false);
},
clickSettingHandler: function(){
if (app.Fence.state == 0)
{
app.Fence.initTouchEvent();
if (app.Fence.polygon){
app.BM.map.removeOverlay(app.Fence.polygon);
}
app.Fence.resetData();
app.Fence.state = 1;
app.Fence.setElementHidden('fence_show');
app.Fence.setElementDisplay('fence_begin_draw');
document.getElementById('action').innerHTML = "取消";
} else {
app.Fence.removeTouchEvent();
if (app.Fence.polyline) {
app.BM.map.removeOverlay(app.Fence.polyline);
}
app.Fence.resetData();
app.Fence.state = 0;
if (app.Fence.cache_points) {
app.Fence.polygon = new BMap.Polygon(app.Fence.cache_points, app.Fence.polylineOption);
app.BM.map.addOverlay(app.Fence.polygon);
}
app.Fence.setElementDisplay('fence_show');
app.Fence.setElementHidden('fence_begin_draw');
document.getElementById('action').innerHTML = "设定";
}
},
finishDrawing: function(){
app.Fence.state = 2;
// 画图完成后立即清除移动
app.Fence.removeTouchEvent();
app.Fence.setElementHidden('fence_begin_draw');
app.Fence.setElementDisplay('fence_end_draw');
},
drawPolygon: function(){
app.BM.map.removeOverlay(app.Fence.polyline);
app.Fence.polygon = new BMap.Polygon(app.Fence.points, app.Fence.polylineOption);
app.BM.map.addOverlay(app.Fence.polygon);
},
removeClickEvent: function(){
document.getElementById('setok').removeEventListener('click', app.Fence.setOKHandler, false);
document.getElementById('reset').removeEventListener('click', app.Fence.resetHandler, false);
},
setOKHandler: function(){
app.Fence.state = 0;
// 最后画一个多边形polygon
app.Fence.drawPolygon();
app.Fence.setElementDisplay('fence_show');
app.Fence.setElementHidden('fence_end_draw');
document.getElementById('action').innerHTML = "设定";
document.getElementById('setting_state').innerHTML = "电子栏栅设定成功";
// 缓存数据
app.Fence.cache_points = app.Fence.points;
// @todo 同步数据到服务器
},
// 不满意,重新画图
resetHandler: function(){
app.Fence.state = 1;
app.BM.map.removeOverlay(app.Fence.polyline);
app.Fence.resetData();
app.Fence.initTouchEvent();
app.Fence.setElementHidden('fence_end_draw');
app.Fence.setElementDisplay('fence_begin_draw');
},
// 触摸事件 @important 开始画图时init 画完图后remove
initTouchEvent: function(){
app.BM.map.addEventListener("touchstart", app.Fence.touchStartHandler, false);
app.BM.map.addEventListener("touchend", app.Fence.touchEndHandler, false);
app.BM.map.addEventListener("touchmove", app.Fence.touchMoveHandler, false);
},
removeTouchEvent: function(){
app.BM.map.removeEventListener("touchstart", app.Fence.touchStartHandler, false);
app.BM.map.removeEventListener("touchend", app.Fence.touchEndHandler, false);
app.BM.map.removeEventListener("touchmove", app.Fence.touchMoveHandler, false);
},
touchStartHandler: function(){
app.BM.map.disableDragging();
app.Bm.map.disableScrollWheelZoom();
},
touchEndHandler: function(){
// 正确的画完图形
if (app.Fence.isOver){
app.Fence.finishDrawing();
} else {
if (!app.Fence.finalCheckIsCrossed())
{
var last = app.Fence.points.length - 1;
app.Fence.polyline = new BMap.Polyline([app.Fence.points[0], app.Fence.points[last]], app.Fence.polylineOption); //创建多边形
app.BM.map.addOverlay(app.Fence.polyline);
app.Fence.finishDrawing();
}
else
{
alert("电子栏栅设定错误,请重新设定!");
app.BM.map.removeOverlay(app.Fence.polyline);
app.Fence.resetData();
app.Fence.state = 1;
app.Fence.setElementHidden('fence_end_draw');
app.Fence.setElementDisplay('fence_begin_draw');
}
}
app.BM.map.enableDragging();
app.BM.map.enableScrollWheelZoom();
},
touchMoveHandler: function(e){
app.Fence.cur_point = e.point;
app.Fence.cur_pixel = e.pixel;
app.Fence.points.push(e.point);
app.Fence.coordinate.push(e.pixel);
if (app.Fence.checkIsCrossed())
{
app.Fence.redrawPolyline();
app.Fence.isOver = true;
}
else
{
if (!app.Fence.isOver) app.Fence.redraw();
}
},
checkIsCrossed: function(){
var last = app.Fence.coordinate.length - 1;
for (var i = 1; i < last - 2; i++)
{
if (last > 5 && app.Fence.intersect(app.Fence.coordinate[last-1], app.Fence.coordinate[last], app.Fence.coordinate[i-1], app.Fence.coordinate[i]))
{
app.Fence.cross_at = i;
return true;
}
}
return false;
},
finalCheckIsCrossed: function(){
var last = app.Fence.coordinate.length - 1;
for (var i = 2; i < last - 2; i++)
{
if (app.Fence.intersect(app.Fence.coordinate[i-1], app.Fence.coordinate[i], app.Fence.coordinate[0], app.Fence.coordinate[last]))
{
return true;
}
}
return false;
},
redrawPolyline: function(){
app.Fence.points.splice(0, app.Fence.cross_at);
// 重画图形
if (app.Fence.polyline) {
app.BM.map.removeOverlay(app.Fence.polyline);
}
if (app.Fence.points)
{
app.Fence.polyline = new BMap.Polyline(app.Fence.points, app.Fence.polylineOption); //创建多边形
app.BM.map.addOverlay(app.Fence.polyline); //增加多边形
var last = app.Fence.points.length -1 ;
app.Fence.polyline = new BMap.Polyline([app.Fence.points[0], app.Fence.points[last]], app.Fence.polylineOption); //创建多边形
app.BM.map.addOverlay(app.Fence.polyline);
}
},
redraw: function(){
if (app.Fence.polyline) {
app.BM.map.removeOverlay(app.Fence.polyline);
}
if (app.Fence.points)
{
app.Fence.polyline = new BMap.Polyline(app.Fence.points, app.Fence.polylineOption); //创建多边形
app.BM.map.addOverlay(app.Fence.polyline); //增加多边形
}
},
/* 叉积 判断2条线段是否相交 */
mult: function(a, b, c) {
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
},
/* pa, pb为一条线段两端点 pc, pd为另一条线段的两端点 相交返回true, 不相交返回false*/
intersect: function(pa, pb, pc, pd) {
if ( Math.max(pa.x, pb.x)<Math.min(pc.x, pd.x) )
{
return false;
}
if ( Math.max(pa.y, pb.y)<Math.min(pc.y, pd.y) )
{
return false;
}
if ( Math.max(pc.x, pd.x)<Math.min(pa.x, pb.x) )
{
return false;
}
if ( Math.max(pc.y, pd.y)<Math.min(pa.y, pb.y) )
{
return false;
}
if ( app.Fence.mult(pc, pb, pa)*app.Fence.mult(pb, pd, pa)<0 )
{
return false;
}
if ( app.Fence.mult(pa, pd, pc)*app.Fence.mult(pd, pb, pc)<0 )
{
return false;
}
return true;
},
resetData: function(){
app.Fence.polyline = false;
app.Fence.points = [];
app.Fence.coordinate = [];
app.Fence.isOver = false;
app.Fence.cur_point = false;
app.Fence.cur_pixel = false;
app.Fence.polygon = false;
},
setElementDisplay:function(id){
document.getElementById(id).style.display = "block";
},
setElementHidden: function(id){
document.getElementById(id).style.display = "none";
}
};
Mr.crow
answered 9 years, 5 months ago