jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page import="com.mmsys.extension.common.SystemParamUtil"%>
<%@ page import="com.mmsys.extension.common.constant.SystemParamConstant"%>
<%
String version = SystemParamUtil.getParam(SystemParamConstant.VERSION);
%>
<c:set var="ctx" value="${pageContext.request.contextPath}"></c:set>
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="<c:url value='/img/favicon.ico'/>" type="image/x-icon" />
<link rel="stylesheet" type="text/css" id="theme" href="<c:url value='/css/theme-default.css'/>?<%=SystemParamConstant.VERSION %>=<%=version %>" />
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=Ycn0TNjsFIKfA9dijTxFdAGRXakQc8wV"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bmap/drawingManager.js'/>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bmap/graphicValid.js'/>"></script>
<link rel="stylesheet" href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" />
<script type="text/javascript" src="http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js"></script>
<link rel="stylesheet" type="text/css" id="theme" href="<c:url value='/css/ztree/metroStyle.css'/>?<%=SystemParamConstant.VERSION %>=<%=version %> "/>
<style type="text/css">
#allmap {width: 100%; height:600px; overflow: hidden;}
dl,dt,dd,ul,li{
margin:0;
padding:0;
list-style:none;
}
p{font-size:12px;}
dt{
font-size:14px;
font-family:"微软雅黑";
font-weight:bold;
border-bottom:1px dotted #000;
padding:5px 0 5px 5px;
margin:5px 0;
}
dd{
padding:5px 0 0 5px;
}
li{
line-height:28px;
}
</style>
</head>
<body>
<div class="page-container">
<%@ include file="menu.jsp"%>
<div class="page-content">
<%@ include file="top.jsp"%>
<div class="page-content-wrap">
<form:form role="form" class="form-horizontal" method="post">
<div class="row">
<div class="col-md-12">
<div class="panel-heading">
<div class="form-group">
<div class="col-md-4">
<div class="content_wrap">
<div class="zTreeDemoBackground left">
<ul class="list">
<li class="title">
揽投部:<input id="deliverName" type="text" value="" style="width:300px; height:27px; border:1px solid #DDD;" οnfοcus="deliver_onfocus(this.value)" οninput="deliver_oninput(this.value);"/>
<input id="deliverId" type="hidden"/>
</li>
</ul>
</div>
</div>
<div id="menuContent" style=" margin-top:-1px; margin-left: 48px; display:none; width:300px; height:300px; position:absolute;z-index:99999; background-color: #fff; overflow-x: hidden; overflow-y: auto; border:1px solid #DDD;">
<ul id="ztree_deliver" class="ztree" ></ul>
</div>
</div>
<div class="col-md-4">
<button class="btn btn-default pull-right" οnclick="grid_submit()" type="button"><i class="fa fa-save"><font class="iconFont"> 保存</font></i></button>
<button class="btn btn-default pull-right" οnclick="grid_update_cancel()" type="button"><i class="fa fa-times-circle-o"><font class="iconFont"> 取消</font></i></button>
<button class="btn btn-default pull-right" οnclick="grid_update()" type="button"><i class="fa fa-edit"><font class="iconFont"> 修改</font></i></button>
<button class="btn btn-default pull-right" οnclick="grid_delete()" type="button"><i class="fa fa-trash-o"><font class="iconFont"> 删除</font></i> </button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="allmap" style="overflow:hidden; position:absolute;z-index:0;">
<div id="map" style="height:100%;-webkit-transition: all 0.5s ease-in-out;transition: all 0.5s ease-in-out;"></div>
</div>
</div>
</div>
</form:form>
</div>
</div>
</div>
<div class="modal fade" id="BMap_submit_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="msg_modal_title">信息提示</h4>
</div>
<div class="modal-body">
<p id="msg_modal_text">请确认电子围栏信息准确无误!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-ok btn-success" id="submit_modal_ok">确认</a>
</div>
</div>
</div>
</div>
<div class="modal fade" id="BMap_delete_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="msg_modal_title">删除</h4>
</div>
<div class="modal-body">
<p id="msg_modal_text">你确定要删除全部电子围栏信息吗?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-ok btn-success" id="delete_modal_ok">删除</a>
</div>
</div>
</div>
</div>
<!-- START SCRIPTS -->
<script type="text/javascript" src="<c:url value='/js/plugins/jquery/jquery.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/jquery/jquery-ui.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type='text/javascript' src="<c:url value='/js/plugins/icheck/icheck.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/mcustomscrollbar/jquery.mCustomScrollbar.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap-datepicker.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap-file-input.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap-select.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/tagsinput/jquery.tagsinput.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/noty/jquery.noty.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/noty/layouts/center.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/noty/themes/default.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/actions.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/agency_grid.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/ztree/jquery.ztree.core.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/ztree/jquery.ztree.exhide.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript">
var overlays = []; //存放polygon对象 (添加和修改的对象存储)
var previousPoint = null;
var firstPoint = null;
var polygon_array = new Array();
var map = new BMap.Map('map', {enableMapClick:false});
map.centerAndZoom("沈阳", 13);
//map.enableScrollWheelZoom(); //开启鼠标滑轮滚动
var styleOptions = {
strokeColor:"blue", //边线颜色。
strokeWeight: 1.5, //边线的宽度,以像素为单位。
strokeOpacity: 1, //边线透明度,取值范围0 - 1。
strokeStyle: 'solid', //边线的样式,solid或dashed。
fillOpacity : 0,
}
var overlaycomplete = function(e){
var polygon = e.overlay;
//添加完成时赋值ID
polygon.deliverId = $('#deliverId').val();
polygon.cidstr = '';
polygon.addEventListener('lineupdate', update_overlays(polygon));
//只有在绘图完成的时候清空previousPoint
previousPoint = null;
firstPoint = null;
polygon_array = new Array();
};
//实例化鼠标绘制工具
var drawingManager = new BMapLib.DrawingManager(map, {
isOpen: false, //是否开启绘制模式
enableDrawingTool: true, //是否显示工具栏
drawingToolOptions: {
anchor: BMAP_ANCHOR_TOP_RIGHT, //位置
offset: new BMap.Size(5, 5), //偏离值
},
polygonOptions: styleOptions, //多边形的样式
});
//添加鼠标绘制工具监听事件,用于获取绘制结果
drawingManager.addEventListener('overlaycomplete', overlaycomplete);
var top_left_navigation = new BMap.NavigationControl(); //左上角,添加默认缩放平移控件
var top_left_control = new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT});// 左上角,添加比例尺
//添加控件和比例尺
map.addControl(top_left_navigation);
map.addControl(top_left_control);
$(document).ready(function(){
initTree("ztree_deliver", JSON.parse('${deliverTreeList}'));
queryOverlays();
});
//初始化加载
function queryOverlays(){
clearOverlays();
$.ajax({
url : 'queryGrids.do',
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
},
success : function(data) {
if(data != ""){
for(var i = 0; i < data.length; i ++){
var pointArray = new Array();
var entity = data[i];
var grids = JSON.parse(entity.ccoordinate);
for(var j = 0; j < grids.length; j ++){
pointArray[j] = new BMap.Point(grids[j].lng, grids[j].lat);
}
var polygon = new BMap.Polygon(pointArray, styleOptions);
//调用计算中心点方法 返回Point
var point = getCenterPointWithPolygon(pointArray);
var label = new BMap.Label(entity.deliverName,{offset: new BMap.Size(entity.deliverName.length * -9, 0),position:new BMap.Point(point.lng, point.lat)});
label.setStyle({
color : "#fff",
fontSize : "12px",
height : "20px",
lineHeight : "18px",
padding : "0px " + entity.deliverName.length * 13 + "px 2px 5px",
backgroundColor: "#2e8af1",
borderColor : "#2e8af1",
borderRadius : "5px",
});
polygon.deliverId = entity.deliverId;
polygon.cidstr = entity.cidstr;
polygon.label = label;
map.addOverlay(polygon);
map.addOverlay(label);
//防止没触发完成状态就点击保存
previousPoint = null;
firstPoint = null;
polygon_array = new Array();
drawingManager.close();
}
}
},
error : function(data) {
noty_info('加载失败', 'error');
return false;
}
});
}
//提交
function grid_submit(){
if($('#deliverId').val() == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
//需要校验是否有重叠,主要是修改的时候拖动覆盖物造成的
if(!graphicValid_update()){
return false;
}
var box = $("#BMap_submit_modal");
box.modal();
$("#submit_modal_ok").off();
$("#submit_modal_ok").on("click", function() {
var polygon_array = new Array();
var grids = "[";
for(var i = 0; i < overlays.length; i++){
var overlay = overlays[i].getPath();
var cid = overlays[i].cidstr;
polygon_array.push(overlays[i]);
if (typeof(cid) == "undefined" || cid == "") {
cid = "0";
}
grids += "{'cid':" + cid + ", 'ccoordinate':'[";
for(var j = 0; j < overlay.length; j++){
var grid = overlay[j];
if(j == 0){
grids += "{\"lat\":\"" + grid.lat + "\",\"lng\":\"" + grid.lng + "\"}";
}else{
grids += ",{\"lat\":\"" + grid.lat + "\",\"lng\":\"" + grid.lng + "\"}";
}
}
grids += "]'},";
}
if (grids.length > 1) {
grids = grids.substr(0, grids.length - 1);
}
grids += "]";
$.ajax({
url : 'saveGrids.do',
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
},
data : JSON.stringify({"deliverId" : $('#deliverId').val(), "grids" : grids}),
success : function(data) {
noty_info('保存成功', 'success');
//grid_update_cancel();
queryOverlays();
overlays = [];
},
error : function(data) {
noty_info('保存失败', 'error');
return false;
}
});
box.modal('hide');
});
}
//修改
function grid_update(){
var deliverId = $('#deliverId').val();
if(deliverId == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && deliverId == polygon.deliverId){
polygon.enableEditing();
polygon.addEventListener('lineupdate', update_overlays(polygon));
}
}
//关闭制图状态
drawingManager.close();
}
//编辑的时候将当前对象放入集合中
function update_overlays(polygon){
if(overlays.indexOf(polygon) == -1){
overlays.push(polygon);
}
}
//取消编辑状态
function grid_update_cancel(){
var deliverId = $('#deliverId').val();
if(deliverId == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && deliverId == polygon.deliverId){
polygon.disableEditing();
polygon.removeEventListener('lineupdate', update_overlays);
}
}
//打开
//drawingManager.open();
}
//删除
function grid_delete(){
var deliverId = $('#deliverId').val();
if(deliverId == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
var box = $("#BMap_delete_modal");
box.modal();
$("#delete_modal_ok").off();
$("#delete_modal_ok").on("click", function() {
$.ajax({
url : 'deleteGrids.do',
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
},
data : deliverId,
success : function(data) {
deleteOverlays(deliverId);
noty_info('删除成功', 'success');
},
error : function(data) {
noty_info('删除失败', 'error');
return false;
}
});
box.modal('hide');
});
}
//删除地图上某个揽投部覆盖物
function deleteOverlays(deliverId){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && deliverId == polygon.deliverId){
map.removeOverlay(polygon);
map.removeOverlay(polygon.label);
}
}
overlays = [];
}
//清除地图上所有自定义覆盖物
function clearOverlays(){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]'){
map.removeOverlay(polygon);
map.removeOverlay(polygon.label);
}
}
}
//当前揽投部填充颜色切换
function changeOverlays(value, e){
//如果有修改未保存的数据需要弹窗提示
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
if(allOverlays[i].toString() == '[object Polygon]'){
var polygon = allOverlays[i];
polygon.removeEventListener('lineupdate', update_overlays);
polygon.disableEditing();
if(value == polygon.deliverId){
polygon.setFillColor("#ada5aa");
var zoom = map.getZoom();
map.setViewport(polygon.getPath());
map.setZoom(zoom);
}else{
polygon.setFillColor("white");
}
}
}
drawingManager.close();
//切换下拉框后清除页面所有操作元素
overlays = [];
}
//图形校验(1、图形与图形的关系, 以及之前的图形和当前点的关系)
function graphicValid(point){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && typeof(polygon.deliverId) != "undefined"){
if(previousPoint != null){
var result = isLineCrossPolygon(previousPoint, point, polygon.getPath());
if(result){
noty_info("揽投部区域重叠", "error");
return false;
}
}else{
//此判断能防止先画大圈后画小圈的问题(覆盖物重叠)
var result = BMapLib.GeoUtils.isPointInPolygon(point, polygon);
if(result){
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
return true
}
//判断先画小圈再画大圈的情况
function graphicOverlap(point){
polygon_array.push(point);
if(polygon_array.length >= 3){
var polygon = new BMap.Polygon(polygon_array, styleOptions);
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
if(allOverlays[i].toString() == '[object Polygon]' && typeof(allOverlays[i].deliverId) != "undefined"){
var overlay = allOverlays[i].getPath();
for(var j = 0; j < overlay.length; j ++){
var old_point = overlay[j];
var result = BMapLib.GeoUtils.isPointInPolygon(old_point, polygon);
if(result){
//如果是重叠的,那么要删除当前polygon_array的点
var index = polygon_array.indexOf(point);
if(index > -1){
polygon_array.splice(index, 1);
}
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
}
if(firstPoint == null){
firstPoint = point;
}
previousPoint = point;
return true;
}
//完成时判断最后一点和第一个点连线
function overlaycompleteValid(point){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && typeof(polygon.deliverId) != "undefined"){
if(previousPoint != null){
var result = isLineCrossPolygon(firstPoint, point, polygon.getPath());
if(result){
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
return true
}
//图形校验(判断更改后是否有图形重叠)
function graphicValid_update() {
var allOverlays = map.getOverlays();
for (var i = 0; i < overlays.length; i ++) {
var overlay = overlays[i].getPath();
for (var k = 0; k < allOverlays.length; k ++) {
var polygon = allOverlays[k];
if(polygon == overlays[i] || polygon.toString() != '[object Polygon]'){
continue;
}
for (var j = 0; j < overlay.length - 1; j ++) {
var point1 = overlay[j];
var point2 = overlay[j + 1];
var result = isLineCrossPolygon(point1, point2, polygon.getPath());
if (result) {
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
return true
}
//打开绘图工具事件
function drawing_onclick(e) {
if ($('#deliverId').val() == '') {
if (e && e.stopPropagation) {
//因此它支持W3C的stopPropagation()方法
e.preventDefault();
e.stopPropagation();
} else {
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
noty_info("请选择揽投部信息", "error");
}
}
function noty_info(text, type) {
noty({
text : text,
layout : 'center',
type : type,
timeout : 2000
});
}
</script>
</body>
</html>
js
var setting = {
view : {
dblClickExpand : false,
selectedMulti : false
},
data : {
simpleData : {
enable : true,
idKey : "strId",
pIdKey : "strParentid"
},
key : {
name : "cname"
}
},
callback : {
beforeClick : beforeClick,
onClick : onClick
}
};
function initTree(treeid, zNodes) {
var newNode = {
strId : 0,
cname : "揽投部"
};
zNodes.push(newNode);
var treeObj = $.fn.zTree.init($("#" + treeid), setting, zNodes);
treeObj.expandAll(true);
}
function beforeClick(treeId, treeNode) {
var check = (treeNode && !treeNode.isParent);
if (!check){
noty_info("只能选择子节点...", "error");
}
return check;
}
function onClick(e, treeId, treeNode) {
var zTree = $.fn.zTree.getZTreeObj("ztree_deliver");
var nodes = zTree.getSelectedNodes();
$("#deliverName").val(nodes[0].cname);
$("#deliverId").val(nodes[0].strId);
changeOverlays(nodes[0].strId);
hideMenu();
}
function deliver_onfocus(value){
showMenu();
if(value != ""){
var zTree = $.fn.zTree.getZTreeObj("ztree_deliver");
var shownodes = zTree.getNodesByParam("isHidden", true);
zTree.showNodes(shownodes);
var deliverId = $("#deliverId").val();
if(deliverId != ""){
//根据Id高亮显示上一次选择树
var nodes = zTree.transformToArray(zTree.getNodes());
for(var i = 0 ; i < nodes.length; i ++){
if(nodes[i].strId == deliverId){
nodes[i].highlight = true;
zTree.updateNode(nodes[i]);
}
}
}
}
}
function deliver_oninput(value){
//树的过滤
var zTree = $.fn.zTree.getZTreeObj("ztree_deliver");
var shownodes = zTree.getNodesByParam("isHidden", true);
zTree.showNodes(shownodes);
zTree.getNodesByFilter(nodeFilter(zTree, value));
}
function nodeFilter(zTree, value){
var showNodes = new Array();
var allNodes = zTree.transformToArray(zTree.getNodes());
zTree.hideNodes(allNodes);
for(var i = 0 ; i < allNodes.length; i ++){
if(allNodes[i].cname.indexOf(value) >= 0){
showNodes.push(allNodes[i]);
}
}
if(showNodes.length == 0){
return false;
}
var resultNodes = new Array();
for(var i = 0; i < showNodes.length; i ++){
getParentNode(showNodes[i], resultNodes);
}
zTree.showNodes(resultNodes);
zTree.expandAll(true);
}
function getParentNode(node, resultNodes) {
if (node != null && node != "") {
resultNodes.push(node);
var parentNode = node.getParentNode();
return getParentNode(parentNode, resultNodes);
} else {
return;
}
}
function showMenu() {
$("#menuContent").slideDown("fast");
$("body").bind("mousedown", onBodyDown);
}
function hideMenu() {
$("#menuContent").fadeOut("fast");
$("body").unbind("mousedown", onBodyDown);
}
function onBodyDown(event) {
if (!(event.target.id == "menuBtn" || event.target.id == "menuContent" || $(event.target).parents("#menuContent").length > 0)) {
hideMenu();
$("#deliverName").blur();
}
}
/**
* @fileoverview 百度地图的鼠标绘制工具,对外开放。
* 允许用户在地图上点击完成鼠标绘制的功能。
* 使用者可以自定义所绘制结果的相关样式,例如线宽、颜色、测线段距离、面积等等。
* 主入口类是<a href="symbols/BMapLib.DrawingManager.html">DrawingManager</a>,
* 基于Baidu Map API 1.4。
*
* @author Baidu Map Api Group
* @version 1.4
*/
/**
* @namespace BMap的所有library类均放在BMapLib命名空间下
*/
var BMapLib = window.BMapLib = BMapLib || {};
/**
* 定义常量, 绘制的模式
* @final {Number} DrawingType
*/
var BMAP_DRAWING_MARKER = "marker", // 鼠标画点模式
BMAP_DRAWING_POLYLINE = "polyline", // 鼠标画线模式
BMAP_DRAWING_CIRCLE = "circle", // 鼠标画圆模式
BMAP_DRAWING_RECTANGLE = "rectangle", // 鼠标画矩形模式
BMAP_DRAWING_POLYGON = "polygon"; // 鼠标画多边形模式
(function() {
/**
* 声明baidu包
*/
var baidu = baidu || {guid : "$BAIDU$"};
(function() {
// 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上
window[baidu.guid] = {};
/**
* 将源对象的所有属性拷贝到目标对象中
* @name baidu.extend
* @function
* @grammar baidu.extend(target, source)
* @param {Object} target 目标对象
* @param {Object} source 源对象
* @returns {Object} 目标对象
*/
baidu.extend = function (target, source) {
for (var p in source) {
if (source.hasOwnProperty(p)) {
target[p] = source[p];
}
}
return target;
};
/**
* @ignore
* @namespace
* @baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
* @property guid 对象的唯一标识
*/
baidu.lang = baidu.lang || {};
/**
* 返回一个当前页面的唯一标识字符串。
* @function
* @grammar baidu.lang.guid()
* @returns {String} 当前页面的唯一标识字符串
*/
baidu.lang.guid = function() {
return "TANGRAM__" + (window[baidu.guid]._counter ++).toString(36);
};
window[baidu.guid]._counter = window[baidu.guid]._counter || 1;
/**
* 所有类的实例的容器
* key为每个实例的guid
*/
window[baidu.guid]._instances = window[baidu.guid]._instances || {};
/**
* Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。
* @function
* @name baidu.lang.Class
* @grammar baidu.lang.Class(guid)
* @param {string} guid 对象的唯一标识
* @meta standard
* @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。
* guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>
* baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。
*/
baidu.lang.Class = function(guid) {
this.guid = guid || baidu.lang.guid();
window[baidu.guid]._instances[this.guid] = this;
};
window[baidu.guid]._instances = window[baidu.guid]._instances || {};
/**
* 判断目标参数是否string类型或String对象
* @name baidu.lang.isString
* @function
* @grammar baidu.lang.isString(source)
* @param {Any} source 目标参数
* @shortcut isString
* @meta standard
*
* @returns {boolean} 类型判断结果
*/
baidu.lang.isString = function (source) {
return '[object String]' == Object.prototype.toString.call(source);
};
/**
* 判断目标参数是否为function或Function实例
* @name baidu.lang.isFunction
* @function
* @grammar baidu.lang.isFunction(source)
* @param {Any} source 目标参数
* @returns {boolean} 类型判断结果
*/
baidu.lang.isFunction = function (source) {
return '[object Function]' == Object.prototype.toString.call(source);
};
/**
* 重载了默认的toString方法,使得返回信息更加准确一些。
* @return {string} 对象的String表示形式
*/
baidu.lang.Class.prototype.toString = function(){
return "[object " + (this._className || "Object" ) + "]";
};
/**
* 释放对象所持有的资源,主要是自定义事件。
* @name dispose
* @grammar obj.dispose()
*/
baidu.lang.Class.prototype.dispose = function(){
delete window[baidu.guid]._instances[this.guid];
for(var property in this){
if (!baidu.lang.isFunction(this[property])) {
delete this[property];
}
}
this.disposed = true;
};
/**
* 自定义的事件对象。
* @function
* @name baidu.lang.Event
* @grammar baidu.lang.Event(type[, target])
* @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。
* @param {Object} [target]触发事件的对象
* @meta standard
* @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。
* @see baidu.lang.Class
*/
baidu.lang.Event = function (type, target) {
this.type = type;
this.returnValue = true;
this.target = target || null;
this.currentTarget = null;
};
/**
* 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
* @grammar obj.addEventListener(type, handler[, key])
* @param {string} type 自定义事件的名称
* @param {Function} handler 自定义事件被触发时应该调用的回调函数
* @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。
* @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。
*/
baidu.lang.Class.prototype.addEventListener = function (type, handler, key) {
if (!baidu.lang.isFunction(handler)) {
return;
}
!this.__listeners && (this.__listeners = {});
var t = this.__listeners, id;
if (typeof key == "string" && key) {
if (/[^\w\-]/.test(key)) {
throw("nonstandard key:" + key);
} else {
handler.hashCode = key;
id = key;
}
}
type.indexOf("on") != 0 && (type = "on" + type);
typeof t[type] != "object" && (t[type] = {});
id = id || baidu.lang.guid();
handler.hashCode = id;
t[type][id] = handler;
};
/**
* 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
* @grammar obj.removeEventListener(type, handler)
* @param {string} type 事件类型
* @param {Function|string} handler 要移除的事件监听函数或者监听函数的key
* @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。
*/
baidu.lang.Class.prototype.removeEventListener = function (type, handler) {
if (baidu.lang.isFunction(handler)) {
handler = handler.hashCode;
} else if (!baidu.lang.isString(handler)) {
return;
}
!this.__listeners && (this.__listeners = {});
type.indexOf("on") != 0 && (type = "on" + type);
var t = this.__listeners;
if (!t[type]) {
return;
}
t[type][handler] && delete t[type][handler];
};
/**
* 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
* @grammar obj.dispatchEvent(event, options)
* @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持)
* @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持)
* @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。
* 例如:<br>
* myobj.onMyEvent = function(){}<br>
* myobj.addEventListener("onMyEvent", function(){});
*/
baidu.lang.Class.prototype.dispatchEvent = function (event, options) {
if (baidu.lang.isString(event)) {
event = new baidu.lang.Event(event);
}
!this.__listeners && (this.__listeners = {});
options = options || {};
for (var i in options) {
event[i] = options[i];
}
var i, t = this.__listeners, p = event.type;
event.target = event.target || this;
event.currentTarget = this;
p.indexOf("on") != 0 && (p = "on" + p);
baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments);
if (typeof t[p] == "object") {
for (i in t[p]) {
t[p][i].apply(this, arguments);
}
}
return event.returnValue;
};
/**
* 为类型构造器建立继承关系
* @name baidu.lang.inherits
* @function
* @grammar baidu.lang.inherits(subClass, superClass[, className])
* @param {Function} subClass 子类构造器
* @param {Function} superClass 父类构造器
* @param {string} className 类名标识
* @remark 使subClass继承superClass的prototype,
* 因此subClass的实例能够使用superClass的prototype中定义的所有属性和方法。<br>
* 这个函数实际上是建立了subClass和superClass的原型链集成,并对subClass进行了constructor修正。<br>
* <strong>注意:如果要继承构造函数,需要在subClass里面call一下,具体见下面的demo例子</strong>
* @shortcut inherits
* @meta standard
* @see baidu.lang.Class
*/
baidu.lang.inherits = function (subClass, superClass, className) {
var key, proto,
selfProps = subClass.prototype,
clazz = new Function();
clazz.prototype = superClass.prototype;
proto = subClass.prototype = new clazz();
for (key in selfProps) {
proto[key] = selfProps[key];
}
subClass.prototype.constructor = subClass;
subClass.superClass = superClass.prototype;
if ("string" == typeof className) {
proto._className = className;
}
};
/**
* @ignore
* @namespace baidu.dom 操作dom的方法。
*/
baidu.dom = baidu.dom || {};
/**
* 从文档中获取指定的DOM元素
*
* @param {string|HTMLElement} id 元素的id或DOM元素
* @meta standard
* @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数
*/
baidu._g = baidu.dom._g = function (id) {
if (baidu.lang.isString(id)) {
return document.getElementById(id);
}
return id;
};
/**
* 从文档中获取指定的DOM元素
* @name baidu.dom.g
* @function
* @grammar baidu.dom.g(id)
* @param {string|HTMLElement} id 元素的id或DOM元素
* @meta standard
*
* @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数
*/
baidu.g = baidu.dom.g = function (id) {
if ('string' == typeof id || id instanceof String) {
return document.getElementById(id);
} else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
return id;
}
return null;
};
/**
* 在目标元素的指定位置插入HTML代码
* @name baidu.dom.insertHTML
* @function
* @grammar baidu.dom.insertHTML(element, position, html)
* @param {HTMLElement|string} element 目标元素或目标元素的id
* @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd
* @param {string} html 要插入的html
* @remark
*
* 对于position参数,大小写不敏感<br>
* 参数的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd <br />
* 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。
*
* @shortcut insertHTML
* @meta standard
*
* @returns {HTMLElement} 目标元素
*/
baidu.insertHTML = baidu.dom.insertHTML = function (element, position, html) {
element = baidu.dom.g(element);
var range,begin;
if (element.insertAdjacentHTML) {
element.insertAdjacentHTML(position, html);
} else {
// 这里不做"undefined" != typeof(HTMLElement) && !window.opera判断,其它浏览器将出错?!
// 但是其实做了判断,其它浏览器下等于这个函数就不能执行了
range = element.ownerDocument.createRange();
// FF下range的位置设置错误可能导致创建出来的fragment在插入dom树之后html结构乱掉
// 改用range.insertNode来插入html, by wenyuxiang @ 2010-12-14.
position = position.toUpperCase();
if (position == 'AFTERBEGIN' || position == 'BEFOREEND') {
range.selectNodeContents(element);
range.collapse(position == 'AFTERBEGIN');
} else {
begin = position == 'BEFOREBEGIN';
range[begin ? 'setStartBefore' : 'setEndAfter'](element);
range.collapse(begin);
}
range.insertNode(range.createContextualFragment(html));
}
return element;
};
/**
* 为目标元素添加className
* @name baidu.dom.addClass
* @function
* @grammar baidu.dom.addClass(element, className)
* @param {HTMLElement|string} element 目标元素或目标元素的id
* @param {string} className 要添加的className,允许同时添加多个class,中间使用空白符分隔
* @remark
* 使用者应保证提供的className合法性,不应包含不合法字符,className合法字符参考:http://www.w3.org/TR/CSS2/syndata.html。
* @shortcut addClass
* @meta standard
*
* @returns {HTMLElement} 目标元素
*/
baidu.ac = baidu.dom.addClass = function (element, className) {
element = baidu.dom.g(element);
var classArray = className.split(/\s+/),
result = element.className,
classMatch = " " + result + " ",
i = 0,
l = classArray.length;
for (; i < l; i++){
if ( classMatch.indexOf( " " + classArray[i] + " " ) < 0 ) {
result += (result ? ' ' : '') + classArray[i];
}
}
element.className = result;
return element;
};
/**
* @ignore
* @namespace baidu.event 屏蔽浏览器差异性的事件封装。
* @property target 事件的触发元素
* @property pageX 鼠标事件的鼠标x坐标
* @property pageY 鼠标事件的鼠标y坐标
* @property keyCode 键盘事件的键值
*/
baidu.event = baidu.event || {};
/**
* 事件监听器的存储表
* @private
* @meta standard
*/
baidu.event._listeners = baidu.event._listeners || [];
/**
* 为目标元素添加事件监听器
* @name baidu.event.on
* @function
* @grammar baidu.event.on(element, type, listener)
* @param {HTMLElement|string|window} element 目标元素或目标元素id
* @param {string} type 事件类型
* @param {Function} listener 需要添加的监听器
* @remark
* 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
* 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败
* @shortcut on
* @meta standard
* @see baidu.event.un
*
* @returns {HTMLElement|window} 目标元素
*/
baidu.on = baidu.event.on = function (element, type, listener) {
type = type.replace(/^on/i, '');
element = baidu._g(element);
var realListener = function (ev) {
// 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
// 2. element是为了修正this
listener.call(element, ev);
},
lis = baidu.event._listeners,
filter = baidu.event._eventFilter,
afterFilter,
realType = type;
type = type.toLowerCase();
// filter过滤
if(filter && filter[type]){
afterFilter = filter[type](element, type, realListener);
realType = afterFilter.type;
realListener = afterFilter.listener;
}
// 事件监听器挂载
if (element.addEventListener) {
element.addEventListener(realType, realListener, false);
} else if (element.attachEvent) {
element.attachEvent('on' + realType, realListener);
}
// 将监听器存储到数组中
lis[lis.length] = [element, type, listener, realListener, realType];
return element;
};
/**
* 为目标元素移除事件监听器
* @name baidu.event.un
* @function
* @grammar baidu.event.un(element, type, listener)
* @param {HTMLElement|string|window} element 目标元素或目标元素id
* @param {string} type 事件类型
* @param {Function} listener 需要移除的监听器
* @shortcut un
* @meta standard
*
* @returns {HTMLElement|window} 目标元素
*/
baidu.un = baidu.event.un = function (element, type, listener) {
element = baidu._g(element);
type = type.replace(/^on/i, '').toLowerCase();
var lis = baidu.event._listeners,
len = lis.length,
isRemoveAll = !listener,
item,
realType, realListener;
//如果将listener的结构改成json
//可以节省掉这个循环,优化性能
//但是由于un的使用频率并不高,同时在listener不多的时候
//遍历数组的性能消耗不会对代码产生影响
//暂不考虑此优化
while (len--) {
item = lis[len];
// listener存在时,移除element的所有以listener监听的type类型事件
// listener不存在时,移除element的所有type类型事件
if (item[1] === type
&& item[0] === element
&& (isRemoveAll || item[2] === listener)) {
realType = item[4];
realListener = item[3];
if (element.removeEventListener) {
element.removeEventListener(realType, realListener, false);
} else if (element.detachEvent) {
element.detachEvent('on' + realType, realListener);
}
lis.splice(len, 1);
}
}
return element;
};
/**
* 获取event事件,解决不同浏览器兼容问题
* @param {Event}
* @return {Event}
*/
baidu.getEvent = baidu.event.getEvent = function (event) {
return window.event || event;
}
/**
* 获取event.target,解决不同浏览器兼容问题
* @param {Event}
* @return {Target}
*/
baidu.getTarget = baidu.event.getTarget = function (event) {
var event = baidu.getEvent(event);
return event.target || event.srcElement;
}
/**
* 阻止事件的默认行为
* @name baidu.event.preventDefault
* @function
* @grammar baidu.event.preventDefault(event)
* @param {Event} event 事件对象
* @meta standard
*/
baidu.preventDefault = baidu.event.preventDefault = function (event) {
var event = baidu.getEvent(event);
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
};
/**
* 停止事件冒泡传播
* @param {Event}
*/
baidu.stopBubble = baidu.event.stopBubble = function (event) {
event = baidu.getEvent(event);
event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
}
})();
/**
* @exports DrawingManager as BMapLib.DrawingManager
*/
var DrawingManager =
/**
* DrawingManager类的构造函数
* @class 鼠标绘制管理类,实现鼠标绘制管理的<b>入口</b>。
* 实例化该类后,即可调用该类提供的open
* 方法开启绘制模式状态。
* 也可加入工具栏进行选择操作。
*
* @constructor
* @param {Map} map Baidu map的实例对象
* @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br />
* {"<b>isOpen</b>" : {Boolean} 是否开启绘制模式
* <br />"<b>enableDrawingTool</b>" : {Boolean} 是否添加绘制工具栏控件,默认不添加
* <br />"<b>drawingToolOptions</b>" : {Json Object} 可选的输入参数,非必填项。可输入选项包括
* <br /> "<b>anchor</b>" : {ControlAnchor} 停靠位置、默认左上角
* <br /> "<b>offset</b>" : {Size} 偏移值。
* <br /> "<b>scale</b>" : {Number} 工具栏的缩放比例,默认为1
* <br /> "<b>drawingModes</b>" : {DrawingType<Array>} 工具栏上可以选择出现的绘制模式,将需要显示的DrawingType以数组型形式传入,如[BMAP_DRAWING_MARKER, BMAP_DRAWING_CIRCLE] 将只显示画点和画圆的选项
* <br />"<b>enableCalculate</b>" : {Boolean} 绘制是否进行测距(画线时候)、测面(画圆、多边形、矩形)
* <br />"<b>markerOptions</b>" : {CircleOptions} 所画的点的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>circleOptions</b>" : {CircleOptions} 所画的圆的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>polylineOptions</b>" : {CircleOptions} 所画的线的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>polygonOptions</b>" : {PolygonOptions} 所画的多边形的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>rectangleOptions</b>" : {PolygonOptions} 所画的矩形的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
*
* @example <b>参考示例:</b><br />
* var map = new BMap.Map("container");<br />map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);<br />
* var myDrawingManagerObject = new BMapLib.DrawingManager(map, {isOpen: true,
* drawingType: BMAP_DRAWING_MARKER, enableDrawingTool: true,
* enableCalculate: false,
* drawingToolOptions: {
* anchor: BMAP_ANCHOR_TOP_LEFT,
* offset: new BMap.Size(5, 5),
* drawingTypes : [
* BMAP_DRAWING_MARKER,
* BMAP_DRAWING_CIRCLE,
* BMAP_DRAWING_POLYLINE,
* BMAP_DRAWING_POLYGON,
* BMAP_DRAWING_RECTANGLE
* ]
* },
* polylineOptions: {
* strokeColor: "#333"
* });
*/
BMapLib.DrawingManager = function(map, opts){
if (!map) {
return;
}
instances.push(this);
opts = opts || {};
this._initialize(map, opts);
}
// 通过baidu.lang下的inherits方法,让DrawingManager继承baidu.lang.Class
baidu.lang.inherits(DrawingManager, baidu.lang.Class, "DrawingManager");
/**
* 开启地图的绘制模式
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.open();
*/
DrawingManager.prototype.open = function() {
// 判断绘制状态是否已经开启
if (this._isOpen == true){
return true;
}
closeInstanceExcept(this);
this._open();
}
/**
* 关闭地图的绘制状态
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.close();
*/
DrawingManager.prototype.close = function() {
// 判断绘制状态是否已经开启
if (this._isOpen == false){
return true;
}
this._close();
}
/**
* 设置当前的绘制模式,参数DrawingType,为5个可选常量:
* <br/>BMAP_DRAWING_MARKER 画点
* <br/>BMAP_DRAWING_CIRCLE 画圆
* <br/>BMAP_DRAWING_POLYLINE 画线
* <br/>BMAP_DRAWING_POLYGON 画多边形
* <br/>BMAP_DRAWING_RECTANGLE 画矩形
* @param {DrawingType} DrawingType
* @return {Boolean}
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.setDrawingMode(BMAP_DRAWING_POLYLINE);
*/
DrawingManager.prototype.setDrawingMode = function(drawingType) {
//与当前模式不一样时候才进行重新绑定事件
if (this._drawingType != drawingType) {
closeInstanceExcept(this);
this._setDrawingMode(drawingType);
}
}
/**
* 获取当前的绘制模式
* @return {DrawingType} 绘制的模式
*
* @example <b>参考示例:</b><br />
* alert(myDrawingManagerObject.getDrawingMode());
*/
DrawingManager.prototype.getDrawingMode = function() {
return this._drawingType;
}
/**
* 打开距离或面积计算
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.enableCalculate();
*/
DrawingManager.prototype.enableCalculate = function() {
this._enableCalculate = true;
this._addGeoUtilsLibrary();
}
/**
* 关闭距离或面积计算
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.disableCalculate();
*/
DrawingManager.prototype.disableCalculate = function() {
this._enableCalculate = false;
}
/**
* 鼠标绘制完成后,派发总事件的接口
* @name DrawingManager#overlaycomplete
* @event
* @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
* <br />{"<b>drawingMode</b> : {DrawingType} 当前的绘制模式
* <br />"<b>overlay</b>:{Marker||Polyline||Polygon||Circle} 对应的绘制模式返回对应的覆盖物
* <br />"<b>calculate</b>:{Number} 需要开启计算模式才会返回这个值,当绘制线的时候返回距离、绘制多边形、圆、矩形时候返回面积,单位为米,
* <br />"<b>label</b>:{Label} 计算面积时候出现在Map上的Label对象
*
* @example <b>参考示例:</b>
* myDrawingManagerObject.addEventListener("overlaycomplete", function(e) {
* alert(e.drawingMode);
* alert(e.overlay);
* alert(e.calculate);
* alert(e.label);
* });
*/
/**
* 绘制点完成后,派发的事件接口
* @name DrawingManager#markercomplete
* @event
* @param {Marker} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Marker}
*
* @example <b>参考示例:</b>
* myDrawingManagerObject.addEventListener("circlecomplete", function(e, overlay) {
* alert(overlay);
* });
*/
/**
* 绘制圆完成后,派发的事件接口
* @name DrawingManager#circlecomplete
* @event
* @param {Circle} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Circle}
*/
/**
* 绘制线完成后,派发的事件接口
* @name DrawingManager#polylinecomplete
* @event
* @param {Polyline} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Polyline}
*/
/**
* 绘制多边形完成后,派发的事件接口
* @name DrawingManager#polygoncomplete
* @event
* @param {Polygon} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Polygon}
*/
/**
* 绘制矩形完成后,派发的事件接口
* @name DrawingManager#rectanglecomplete
* @event
* @param {Polygon} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Polygon}
*/
/**
* 初始化状态
* @param {Map} 地图实例
* @param {Object} 参数
*/
DrawingManager.prototype._initialize = function(map, opts) {
/**
* map对象
* @private
* @type {Map}
*/
this._map = map;
/**
* 配置对象
* @private
* @type {Object}
*/
this._opts = opts;
/**
* 当前的绘制模式, 默认是绘制点
* @private
* @type {DrawingType}
*/
this._drawingType = opts.drawingMode || BMAP_DRAWING_MARKER;
/**
* 是否添加添加鼠标绘制工具栏面板
*/
if (opts.enableDrawingTool) {
var drawingTool = new DrawingTool(this, opts.drawingToolOptions);
this._drawingTool = drawingTool;
map.addControl(drawingTool);
}
//是否计算绘制出的面积
if (opts.enableCalculate === true) {
this.enableCalculate();
} else {
this.disableCalculate();
}
/**
* 是否已经开启了绘制状态
* @private
* @type {Boolean}
*/
this._isOpen = !!(opts.isOpen === true);
if (this._isOpen) {
this._open();
}
this.markerOptions = opts.markerOptions || {};
this.circleOptions = opts.circleOptions || {};
this.polylineOptions = opts.polylineOptions || {};
this.polygonOptions = opts.polygonOptions || {};
this.rectangleOptions = opts.rectangleOptions || {};
},
/**
* 开启地图的绘制状态
* @return {Boolean},开启绘制状态成功,返回true;否则返回false。
*/
DrawingManager.prototype._open = function() {
this._isOpen = true;
//添加遮罩,所有鼠标操作都在这个遮罩上完成
if (!this._mask) {
this._mask = new Mask();
}
this._map.addOverlay(this._mask);
this._setDrawingMode(this._drawingType);
}
/**
* 设置当前的绘制模式
* @param {DrawingType}
*/
DrawingManager.prototype._setDrawingMode = function(drawingType) {
this._drawingType = drawingType;
/**
* 开启编辑状态时候才重新进行事件绑定
*/
if (this._isOpen) {
//清空之前的自定义事件
this._mask.__listeners = {};
switch (drawingType) {
case BMAP_DRAWING_MARKER:
this._bindMarker();
break;
case BMAP_DRAWING_CIRCLE:
this._bindCircle();
break;
case BMAP_DRAWING_POLYLINE:
case BMAP_DRAWING_POLYGON:
this._bindPolylineOrPolygon();
break;
case BMAP_DRAWING_RECTANGLE:
this._bindRectangle();
break;
}
}
/**
* 如果添加了工具栏,则也需要改变工具栏的样式
*/
if (this._drawingTool && this._isOpen) {
this._drawingTool.setStyleByDrawingMode(drawingType);
}
}
/**
* 关闭地图的绘制状态
* @return {Boolean},关闭绘制状态成功,返回true;否则返回false。
*/
DrawingManager.prototype._close = function() {
this._isOpen = false;
if (this._mask) {
this._map.removeOverlay(this._mask);
}
/**
* 如果添加了工具栏,则关闭时候将工具栏样式设置为拖拽地图
*/
if (this._drawingTool) {
this._drawingTool.setStyleByDrawingMode("hander");
}
}
/**
* 绑定鼠标画点的事件
*/
DrawingManager.prototype._bindMarker = function() {
var me = this,
map = this._map,
mask = this._mask;
/**
* 鼠标点击的事件
*/
var clickAction = function (e) {
// 往地图上添加marker
var marker = new BMap.Marker(e.point, me.markerOptions);
map.addOverlay(marker);
me._dispatchOverlayComplete(marker);
}
mask.addEventListener('click', clickAction);
}
/**
* 绑定鼠标画圆的事件
*/
DrawingManager.prototype._bindCircle = function() {
var me = this,
map = this._map,
mask = this._mask,
circle = null,
centerPoint = null; //圆的中心点
/**
* 开始绘制圆形
*/
var startAction = function (e) {
centerPoint = e.point;
circle = new BMap.Circle(centerPoint, 0, me.circleOptions);
map.addOverlay(circle);
mask.enableEdgeMove();
mask.addEventListener('mousemove', moveAction);
baidu.on(document, 'mouseup', endAction);
}
/**
* 绘制圆形过程中,鼠标移动过程的事件
*/
var moveAction = function(e) {
circle.setRadius(me._map.getDistance(centerPoint, e.point));
}
/**
* 绘制圆形结束
*/
var endAction = function (e) {
var calculate = me._calculate(circle, e.point);
me._dispatchOverlayComplete(circle, calculate);
centerPoint = null;
mask.disableEdgeMove();
mask.removeEventListener('mousemove', moveAction);
baidu.un(document, 'mouseup', endAction);
}
/**
* 鼠标点击起始点
*/
var mousedownAction = function (e) {
baidu.preventDefault(e);
baidu.stopBubble(e);
if (centerPoint == null) {
startAction(e);
}
}
mask.addEventListener('mousedown', mousedownAction);
}
/**
* 画线和画多边形相似性比较大,公用一个方法
*/
DrawingManager.prototype._bindPolylineOrPolygon = function() {
var me = this,
map = this._map,
mask = this._mask,
points = [], //用户绘制的点
drawPoint = null; //实际需要画在地图上的点
overlay = null,
isBinded = false;
/**
* 鼠标点击的事件
*/
var startAction = function (e) {
//校验当前点是否合法
var valid_result = graphicValid(e.point);
//var over_result = overlaycompleteValid(e.point);
if(valid_result){
var overlap_valid = graphicOverlap(e.point);
if(overlap_valid){
points.push(e.point);
drawPoint = points.concat(points[points.length - 1]);
if (points.length == 1) {
if (me._drawingType == BMAP_DRAWING_POLYLINE) {
overlay = new BMap.Polyline(drawPoint, me.polylineOptions);
} else if (me._drawingType == BMAP_DRAWING_POLYGON) {
overlay = new BMap.Polygon(drawPoint, me.polygonOptions);
}
map.addOverlay(overlay);
} else {
overlay.setPath(drawPoint);
}
if (!isBinded) {
isBinded = true;
mask.enableEdgeMove();
mask.addEventListener('mousemove', mousemoveAction);
mask.addEventListener('dblclick', dblclickAction);
}
}
}
}
/**
* 鼠标移动过程的事件
*/
var mousemoveAction = function(e) {
overlay.setPositionAt(drawPoint.length - 1, e.point);
}
/**
* 鼠标双击的事件
*/
var dblclickAction = function (e) {
var over_result = overlaycompleteValid(e.point);
if(over_result){
baidu.stopBubble(e);
isBinded = false;
mask.disableEdgeMove();
mask.removeEventListener('mousemove', mousemoveAction);
mask.removeEventListener('dblclick', dblclickAction);
overlay.setPath(points);
var calculate = me._calculate(overlay, points.pop());
me._dispatchOverlayComplete(overlay, calculate);
points.length = 0;
drawPoint.length = 0;
}
}
mask.addEventListener('click', startAction);
//双击时候不放大地图级别
mask.addEventListener('dblclick', function(e){
baidu.stopBubble(e);
});
}
/**
* 绑定鼠标画矩形的事件
*/
DrawingManager.prototype._bindRectangle = function() {
var me = this,
map = this._map,
mask = this._mask,
polygon = null,
startPoint = null;
/**
* 开始绘制矩形
*/
var startAction = function (e) {
baidu.stopBubble(e);
baidu.preventDefault(e);
startPoint = e.point;
var endPoint = startPoint;
polygon = new BMap.Polygon(me._getRectanglePoint(startPoint, endPoint), me.rectangleOptions);
map.addOverlay(polygon);
mask.enableEdgeMove();
mask.addEventListener('mousemove', moveAction);
baidu.on(document, 'mouseup', endAction);
}
/**
* 绘制矩形过程中,鼠标移动过程的事件
*/
var moveAction = function(e) {
polygon.setPath(me._getRectanglePoint(startPoint, e.point));
}
/**
* 绘制矩形结束
*/
var endAction = function (e) {
var calculate = me._calculate(polygon, polygon.getPath()[2]);
me._dispatchOverlayComplete(polygon, calculate);
startPoint = null;
mask.disableEdgeMove();
mask.removeEventListener('mousemove', moveAction);
baidu.un(document, 'mouseup', endAction);
}
mask.addEventListener('mousedown', startAction);
}
/**
* 添加显示所绘制图形的面积或者长度
* @param {overlay} 覆盖物
* @param {point} 显示的位置
*/
DrawingManager.prototype._calculate = function (overlay, point) {
var result = {
data : 0, //计算出来的长度或面积
label : null //显示长度或面积的label对象
};
if (this._enableCalculate && BMapLib.GeoUtils) {
var type = overlay.toString();
//不同覆盖物调用不同的计算方法
switch (type) {
case "[object Polyline]":
result.data = BMapLib.GeoUtils.getPolylineDistance(overlay);
break;
case "[object Polygon]":
result.data = BMapLib.GeoUtils.getPolygonArea(overlay);
break;
case "[object Circle]":
var radius = overlay.getRadius();
result.data = Math.PI * radius * radius;
break;
}
//一场情况处理
if (!result.data || result.data < 0) {
result.data = 0;
} else {
//保留2位小数位
result.data = result.data.toFixed(2);
}
result.label = this._addLabel(point, result.data);
}
return result;
}
/**
* 开启测距和测面功能需要依赖于GeoUtils库
* 所以这里判断用户是否已经加载,若未加载则用js动态加载
*/
DrawingManager.prototype._addGeoUtilsLibrary = function () {
if (!BMapLib.GeoUtils) {
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.setAttribute("src", 'http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js');
document.body.appendChild(script);
}
}
/**
* 向地图中添加文本标注
* @param {Point}
* @param {String} 所以显示的内容
*/
DrawingManager.prototype._addLabel = function (point, content) {
var label = new BMap.Label(content, {
position: point
});
this._map.addOverlay(label);
return label;
}
/**
* 根据起终点获取矩形的四个顶点
* @param {Point} 起点
* @param {Point} 终点
*/
DrawingManager.prototype._getRectanglePoint = function (startPoint, endPoint) {
return [
new BMap.Point(startPoint.lng,startPoint.lat),
new BMap.Point(endPoint.lng,startPoint.lat),
new BMap.Point(endPoint.lng,endPoint.lat),
new BMap.Point(startPoint.lng,endPoint.lat)
];
}
/**
* 派发事件
*/
DrawingManager.prototype._dispatchOverlayComplete = function (overlay, calculate) {
var options = {
'overlay' : overlay,
'drawingMode' : this._drawingType,
'calculate' : calculate.data || null,
'label' : calculate.label || null
};
this.dispatchEvent(this._drawingType + 'complete', overlay);
this.dispatchEvent('overlaycomplete', options);
}
/**
* 创建遮罩对象
*/
function Mask(){
/**
* 鼠标到地图边缘的时候是否自动平移地图
*/
this._enableEdgeMove = false;
}
Mask.prototype = new BMap.Overlay();
/**
* 这里不使用api中的自定义事件,是为了更灵活使用
*/
Mask.prototype.dispatchEvent = baidu.lang.Class.prototype.dispatchEvent;
Mask.prototype.addEventListener = baidu.lang.Class.prototype.addEventListener;
Mask.prototype.removeEventListener = baidu.lang.Class.prototype.removeEventListener;
Mask.prototype.initialize = function(map){
var me = this;
this._map = map;
var div = this.container = document.createElement("div");
var size = this._map.getSize();
div.style.cssText = "position:absolute;background:url(about:blank);cursor:crosshair;width:" + size.width + "px;height:" + size.height + "px";
this._map.addEventListener('resize', function(e) {
me._adjustSize(e.size);
});
this._map.getPanes().floatPane.appendChild(div);
this._bind();
return div;
};
Mask.prototype.draw = function() {
var map = this._map,
point = map.pixelToPoint(new BMap.Pixel(0, 0)),
pixel = map.pointToOverlayPixel(point);
this.container.style.left = pixel.x + "px";
this.container.style.top = pixel.y + "px";
};
/**
* 开启鼠标到地图边缘,自动平移地图
*/
Mask.prototype.enableEdgeMove = function() {
this._enableEdgeMove = true;
}
/**
* 关闭鼠标到地图边缘,自动平移地图
*/
Mask.prototype.disableEdgeMove = function() {
clearInterval(this._edgeMoveTimer);
this._enableEdgeMove = false;
}
/**
* 绑定事件,派发自定义事件
*/
Mask.prototype._bind = function() {
var me = this,
map = this._map,
container = this.container,
lastMousedownXY = null,
lastClickXY = null;
/**
* 根据event对象获取鼠标的xy坐标对象
* @param {Event}
* @return {Object} {x:e.x, y:e.y}
*/
var getXYbyEvent = function(e){
return {
x : e.clientX,
y : e.clientY
}
};
var domEvent = function(e) {
var type = e.type;
e = baidu.getEvent(e);
point = me.getDrawPoint(e); //当前鼠标所在点的地理坐标
var dispatchEvent = function(type) {
e.point = point;
me.dispatchEvent(e);
}
if (type == "mousedown") {
lastMousedownXY = getXYbyEvent(e);
}
var nowXY = getXYbyEvent(e);
//click经过一些特殊处理派发,其他同事件按正常的dom事件派发
if (type == "click") {
//鼠标点击过程不进行移动才派发click和dblclick
if (Math.abs(nowXY.x - lastMousedownXY.x) < 5 && Math.abs(nowXY.y - lastMousedownXY.y) < 5 ) {
if (!lastClickXY || !(Math.abs(nowXY.x - lastClickXY.x) < 5 && Math.abs(nowXY.y - lastClickXY.y) < 5)) {
dispatchEvent('click');
lastClickXY = getXYbyEvent(e);
} else {
lastClickXY = null;
}
}
} else {
dispatchEvent(type);
}
}
/**
* 将事件都遮罩层的事件都绑定到domEvent来处理
*/
var events = ['click', 'mousedown', 'mousemove', 'mouseup', 'dblclick'],
index = events.length;
while (index--) {
baidu.on(container, events[index], domEvent);
}
//鼠标移动过程中,到地图边缘后自动平移地图
baidu.on(container, 'mousemove', function(e) {
if (me._enableEdgeMove) {
me.mousemoveAction(e);
}
});
};
//鼠标移动过程中,到地图边缘后自动平移地图
Mask.prototype.mousemoveAction = function(e) {
function getClientPosition(e) {
var clientX = e.clientX,
clientY = e.clientY;
if (e.changedTouches) {
clientX = e.changedTouches[0].clientX;
clientY = e.changedTouches[0].clientY;
}
return new BMap.Pixel(clientX, clientY);
}
var map = this._map,
me = this,
pixel = map.pointToPixel(this.getDrawPoint(e)),
clientPos = getClientPosition(e),
offsetX = clientPos.x - pixel.x,
offsetY = clientPos.y - pixel.y;
pixel = new BMap.Pixel((clientPos.x - offsetX), (clientPos.y - offsetY));
this._draggingMovePixel = pixel;
var point = map.pixelToPoint(pixel),
eventObj = {
pixel: pixel,
point: point
};
// 拖拽到地图边缘移动地图
this._panByX = this._panByY = 0;
if (pixel.x <= 20 || pixel.x >= map.width - 20
|| pixel.y <= 50 || pixel.y >= map.height - 10) {
if (pixel.x <= 20) {
this._panByX = 8;
} else if (pixel.x >= map.width - 20) {
this._panByX = -8;
}
if (pixel.y <= 50) {
this._panByY = 8;
} else if (pixel.y >= map.height - 10) {
this._panByY = -8;
}
if (!this._edgeMoveTimer) {
this._edgeMoveTimer = setInterval(function(){
map.panBy(me._panByX, me._panByY, {"noAnimation": true});
}, 30);
}
} else {
if (this._edgeMoveTimer) {
clearInterval(this._edgeMoveTimer);
this._edgeMoveTimer = null;
}
}
}
/*
* 调整大小
* @param {Size}
*/
Mask.prototype._adjustSize = function(size) {
this.container.style.width = size.width + 'px';
this.container.style.height = size.height + 'px';
};
/**
* 获取当前绘制点的地理坐标
*
* @param {Event} e e对象
* @return Point对象的位置信息
*/
Mask.prototype.getDrawPoint = function(e) {
var map = this._map,
trigger = baidu.getTarget(e),
x = e.offsetX || e.layerX || 0,
y = e.offsetY || e.layerY || 0;
if (trigger.nodeType != 1) trigger = trigger.parentNode;
while (trigger && trigger != map.getContainer()) {
if (!(trigger.clientWidth == 0 &&
trigger.clientHeight == 0 &&
trigger.offsetParent && trigger.offsetParent.nodeName == 'TD')) {
x += trigger.offsetLeft || 0;
y += trigger.offsetTop || 0;
}
trigger = trigger.offsetParent;
}
var pixel = new BMap.Pixel(x, y);
var point = map.pixelToPoint(pixel);
return point;
}
/**
* 绘制工具面板,自定义控件
*/
function DrawingTool(drawingManager, drawingToolOptions) {
this.drawingManager = drawingManager;
drawingToolOptions = this.drawingToolOptions = drawingToolOptions || {};
// 默认停靠位置和偏移量
this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT;
this.defaultOffset = new BMap.Size(10, 10);
//默认所有工具栏都显示
this.defaultDrawingModes = [
BMAP_DRAWING_MARKER,
BMAP_DRAWING_CIRCLE,
BMAP_DRAWING_POLYLINE,
BMAP_DRAWING_POLYGON,
BMAP_DRAWING_RECTANGLE
];
//工具栏可显示的绘制模式
if (drawingToolOptions.drawingModes) {
this.drawingModes = drawingToolOptions.drawingModes;
} else {
this.drawingModes = this.defaultDrawingModes
}
//用户设置停靠位置和偏移量
if (drawingToolOptions.anchor) {
this.setAnchor(drawingToolOptions.anchor);
}
if (drawingToolOptions.offset) {
this.setOffset(drawingToolOptions.offset);
}
}
// 通过JavaScript的prototype属性继承于BMap.Control
DrawingTool.prototype = new BMap.Control();
// 自定义控件必须实现自己的initialize方法,并且将控件的DOM元素返回
// 在本方法中创建个div元素作为控件的容器,并将其添加到地图容器中
DrawingTool.prototype.initialize = function(map){
// 创建一个DOM元素
var container = this.container = document.createElement("div");
container.className = "BMapLib_Drawing";
//用来设置外层边框阴影
var panel = this.panel = document.createElement("div");
panel.className = "BMapLib_Drawing_panel";
if (this.drawingToolOptions && this.drawingToolOptions.scale) {
this._setScale(this.drawingToolOptions.scale);
}
container.appendChild(panel);
// 添加内容
panel.innerHTML = this._generalHtml();
//绑定事件
this._bind(panel);
// 添加DOM元素到地图中
map.getContainer().appendChild(container);
// 将DOM元素返回
return container;
}
//生成工具栏的html元素
DrawingTool.prototype._generalHtml = function(map){
//鼠标经过工具栏上的提示信息
var tips = {};
tips["hander"] = "拖动地图";
tips[BMAP_DRAWING_MARKER] = "画点";
tips[BMAP_DRAWING_CIRCLE] = "画圆";
tips[BMAP_DRAWING_POLYLINE] = "画折线";
tips[BMAP_DRAWING_POLYGON] = "画多边形";
tips[BMAP_DRAWING_RECTANGLE] = "画矩形";
var getItem = function(className, drawingType) {
var content = '<a class="' + className + '" drawingType="' + drawingType + '" href="javascript:void(0)" title="' + tips[drawingType] + '" οnfοcus="this.blur()"';
if(drawingType == "polygon"){
content += ' οnclick="drawing_onclick(event)"';
}
content += '></a>';
return content;
}
var html = [];
html.push(getItem("BMapLib_box BMapLib_hander", "hander"));
for (var i = 0, len = this.drawingModes.length; i < len; i++) {
var classStr = 'BMapLib_box BMapLib_' + this.drawingModes[i];
if (i == len-1) {
classStr += ' BMapLib_last';
}
if(this.drawingModes[i] == "polygon"){
html.push(getItem(classStr, this.drawingModes[i]));
}
}
return html.join('');
}
/**
* 设置工具栏的缩放比例
*/
DrawingTool.prototype._setScale = function(scale){
var width = 390,
height = 50,
ml = -parseInt((width - width * scale) / 2, 10),
mt = -parseInt((height - height * scale) / 2, 10);
this.container.style.cssText = [
"-moz-transform: scale(" + scale + ");",
"-o-transform: scale(" + scale + ");",
"-webkit-transform: scale(" + scale + ");",
"transform: scale(" + scale + ");",
"margin-left:" + ml + "px;",
"margin-top:" + mt + "px;",
"*margin-left:0px;", //ie6、7
"*margin-top:0px;", //ie6、7
"margin-left:0px\\0;", //ie8
"margin-top:0px\\0;", //ie8
//ie下使用滤镜
"filter: progid:DXImageTransform.Microsoft.Matrix(",
"M11=" + scale + ",",
"M12=0,",
"M21=0,",
"M22=" + scale + ",",
"SizingMethod='auto expand');"
].join('');
}
//绑定工具栏的事件
DrawingTool.prototype._bind = function(panel){
var me = this;
baidu.on(this.panel, 'click', function (e) {
var target = baidu.getTarget(e);
var drawingType = target.getAttribute('drawingType');
me.setStyleByDrawingMode(drawingType);
me._bindEventByDraingMode(drawingType);
});
}
//设置工具栏当前选中的项样式
DrawingTool.prototype.setStyleByDrawingMode = function(drawingType){
if (!drawingType) {
return;
}
var boxs = this.panel.getElementsByTagName("a");
for (var i = 0, len = boxs.length; i < len; i++) {
var box = boxs[i];
if (box.getAttribute('drawingType') == drawingType) {
var classStr = "BMapLib_box BMapLib_" + drawingType + "_hover";
if (i == len - 1) {
classStr += " BMapLib_last";
}
box.className = classStr;
} else {
box.className = box.className.replace(/_hover/, "");
}
}
}
//设置工具栏当前选中的项样式
DrawingTool.prototype._bindEventByDraingMode = function(drawingType){
var drawingManager = this.drawingManager;
//点在拖拽地图的按钮上
if (drawingType == "hander") {
//下行为新增行,根据业务需要修改源代码
drawingManager.setDrawingMode(drawingType);
drawingManager.close();
} else {
drawingManager.setDrawingMode(drawingType);
drawingManager.open();
}
}
//用来存储用户实例化出来的drawingmanager对象
var instances = [];
/*
* 关闭其他实例的绘制模式
* @param {DrawingManager} 当前的实例
*/
function closeInstanceExcept(instance) {
var index = instances.length;
while (index--) {
if (instances[index] != instance) {
instances[index].close();
}
}
}
})();
/**
* 判断两个点相连线段是否与多边形有相交
*
* @param p1 点1
* @param p2 点2
* @param polygon 多边形
*
*/
function isLineCrossPolygon(previousPoint, point, polygon) {
var x1 = previousPoint.lng;
var y1 = previousPoint.lat;
var x2 = point.lng;
var y2 = point.lat;
if (polygon.length < 3) {
return false;
}
for (var index = 0; index < polygon.length; index++) {
var index2 = (index + 1) % polygon.length;
if (isLineCrossLine(x1, y1, x2, y2, polygon[index].lng,
polygon[index].lat, polygon[index2].lng, polygon[index2].lat)) {
return true;
}
}
return false;
}
/**
* 判断线段AB((x1,y1),(x2,y2))和线段CD((x3,y3),(x4,y4))是否相交
*
* @return
*/
function isLineCrossLine(x1, y1, x2, y2, x3, y3, x4, y4) {
// 如果线段的长度为0
if (x1 == x2 && y1 == y2 || x3 == x4 && y3 == y4)
return false;
// 如果两个线段重合
if (x1 == x3 && y1 == y3 || x2 == x3 && y2 == y3 || x1 == x4 && y1 == y4 || x2 == x4 && y2 == y4)
return true;
// 让线段AB的A点与原点(0,0)重合,将两条线段进行整体平移
x2 -= x1;
y2 -= y1;
x3 -= x1;
y3 -= y1;
x4 -= x1;
y4 -= y1;
// 线段AB的长度
var distAB = Math.sqrt(x2 * x2 + y2 * y2);
// 整体旋转两条线段,使线段AB与X轴重合
var theCos = x2 / distAB;
var theSin = y2 / distAB;
var newX = x3 * theCos + y3 * theSin;
y3 = y3 * theCos - x3 * theSin;
x3 = newX;
newX = x4 * theCos + y4 * theSin;
y4 = y4 * theCos - x4 * theSin;
x4 = newX;
// 如果线段CD的Y轴坐标都在X轴的一侧,则不相交
if (y3 < 0 && y4 < 0 || y3 >= 0 && y4 >= 0)
return false;
// 计算直线AB和直线CD的交点
var posAB = x4 + (x3 - x4) * y4 / (y4 - y3);
// 如果交点在X轴的负方向或者交点坐标大于AB长度
if (posAB < 0 || posAB > distAB)
return false;
// 其他情况才相交
return true;
}
/**
* 计算多边形重心点
*
* @param polygon
* @return
*/
function getCenterPointWithPolygon(polygon) {
if (polygon.length < 3)
return;
var p1, p2, p3;
var gx, gy, sumarea;
gx = gy = sumarea = 0.0;
p1 = polygon[0];
p2 = polygon[1];
for (var i = 2; i < polygon.length; i++) {
p3 = polygon[i];
var area = getArea(p1, p2, p3);
gx += (p1.lng + p2.lng + p3.lng) * area;
gy += (p1.lat + p2.lat + p3.lat) * area;
sumarea += area;
p2 = polygon[i];
}
gx = gx / sumarea / 3;
gy = gy / sumarea / 3;
var result = new Object();
result.lng = gx;
result.lat = gy;
return result;
}
/**
* 三角形面积
*/
function getArea(p1, p2, p3) {
return ((p2.lng - p1.lng) * (p3.lat - p1.lat) - (p3.lng - p1.lng) * (p2.lat - p1.lat)) / 2;
}
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page import="com.mmsys.extension.common.SystemParamUtil"%>
<%@ page import="com.mmsys.extension.common.constant.SystemParamConstant"%>
<%
String version = SystemParamUtil.getParam(SystemParamConstant.VERSION);
%>
<c:set var="ctx" value="${pageContext.request.contextPath}"></c:set>
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="<c:url value='/img/favicon.ico'/>" type="image/x-icon" />
<link rel="stylesheet" type="text/css" id="theme" href="<c:url value='/css/theme-default.css'/>?<%=SystemParamConstant.VERSION %>=<%=version %>" />
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=Ycn0TNjsFIKfA9dijTxFdAGRXakQc8wV"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bmap/drawingManager.js'/>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bmap/graphicValid.js'/>"></script>
<link rel="stylesheet" href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" />
<script type="text/javascript" src="http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js"></script>
<link rel="stylesheet" type="text/css" id="theme" href="<c:url value='/css/ztree/metroStyle.css'/>?<%=SystemParamConstant.VERSION %>=<%=version %> "/>
<style type="text/css">
#allmap {width: 100%; height:600px; overflow: hidden;}
dl,dt,dd,ul,li{
margin:0;
padding:0;
list-style:none;
}
p{font-size:12px;}
dt{
font-size:14px;
font-family:"微软雅黑";
font-weight:bold;
border-bottom:1px dotted #000;
padding:5px 0 5px 5px;
margin:5px 0;
}
dd{
padding:5px 0 0 5px;
}
li{
line-height:28px;
}
</style>
</head>
<body>
<div class="page-container">
<%@ include file="menu.jsp"%>
<div class="page-content">
<%@ include file="top.jsp"%>
<div class="page-content-wrap">
<form:form role="form" class="form-horizontal" method="post">
<div class="row">
<div class="col-md-12">
<div class="panel-heading">
<div class="form-group">
<div class="col-md-4">
<div class="content_wrap">
<div class="zTreeDemoBackground left">
<ul class="list">
<li class="title">
揽投部:<input id="deliverName" type="text" value="" style="width:300px; height:27px; border:1px solid #DDD;" οnfοcus="deliver_onfocus(this.value)" οninput="deliver_oninput(this.value);"/>
<input id="deliverId" type="hidden"/>
</li>
</ul>
</div>
</div>
<div id="menuContent" style=" margin-top:-1px; margin-left: 48px; display:none; width:300px; height:300px; position:absolute;z-index:99999; background-color: #fff; overflow-x: hidden; overflow-y: auto; border:1px solid #DDD;">
<ul id="ztree_deliver" class="ztree" ></ul>
</div>
</div>
<div class="col-md-4">
<button class="btn btn-default pull-right" οnclick="grid_submit()" type="button"><i class="fa fa-save"><font class="iconFont"> 保存</font></i></button>
<button class="btn btn-default pull-right" οnclick="grid_update_cancel()" type="button"><i class="fa fa-times-circle-o"><font class="iconFont"> 取消</font></i></button>
<button class="btn btn-default pull-right" οnclick="grid_update()" type="button"><i class="fa fa-edit"><font class="iconFont"> 修改</font></i></button>
<button class="btn btn-default pull-right" οnclick="grid_delete()" type="button"><i class="fa fa-trash-o"><font class="iconFont"> 删除</font></i> </button>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="allmap" style="overflow:hidden; position:absolute;z-index:0;">
<div id="map" style="height:100%;-webkit-transition: all 0.5s ease-in-out;transition: all 0.5s ease-in-out;"></div>
</div>
</div>
</div>
</form:form>
</div>
</div>
</div>
<div class="modal fade" id="BMap_submit_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="msg_modal_title">信息提示</h4>
</div>
<div class="modal-body">
<p id="msg_modal_text">请确认电子围栏信息准确无误!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-ok btn-success" id="submit_modal_ok">确认</a>
</div>
</div>
</div>
</div>
<div class="modal fade" id="BMap_delete_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="msg_modal_title">删除</h4>
</div>
<div class="modal-body">
<p id="msg_modal_text">你确定要删除全部电子围栏信息吗?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-ok btn-success" id="delete_modal_ok">删除</a>
</div>
</div>
</div>
</div>
<!-- START SCRIPTS -->
<script type="text/javascript" src="<c:url value='/js/plugins/jquery/jquery.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/jquery/jquery-ui.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type='text/javascript' src="<c:url value='/js/plugins/icheck/icheck.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/mcustomscrollbar/jquery.mCustomScrollbar.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap-datepicker.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap-file-input.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/bootstrap/bootstrap-select.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/tagsinput/jquery.tagsinput.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/noty/jquery.noty.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/noty/layouts/center.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/noty/themes/default.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/actions.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/agency_grid.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/ztree/jquery.ztree.core.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript" src="<c:url value='/js/plugins/ztree/jquery.ztree.exhide.min.js'/>?<%=SystemParamConstant.VERSION %>=<%=version %>"></script>
<script type="text/javascript">
var overlays = []; //存放polygon对象 (添加和修改的对象存储)
var previousPoint = null;
var firstPoint = null;
var polygon_array = new Array();
var map = new BMap.Map('map', {enableMapClick:false});
map.centerAndZoom("沈阳", 13);
//map.enableScrollWheelZoom(); //开启鼠标滑轮滚动
var styleOptions = {
strokeColor:"blue", //边线颜色。
strokeWeight: 1.5, //边线的宽度,以像素为单位。
strokeOpacity: 1, //边线透明度,取值范围0 - 1。
strokeStyle: 'solid', //边线的样式,solid或dashed。
fillOpacity : 0,
}
var overlaycomplete = function(e){
var polygon = e.overlay;
//添加完成时赋值ID
polygon.deliverId = $('#deliverId').val();
polygon.cidstr = '';
polygon.addEventListener('lineupdate', update_overlays(polygon));
//只有在绘图完成的时候清空previousPoint
previousPoint = null;
firstPoint = null;
polygon_array = new Array();
};
//实例化鼠标绘制工具
var drawingManager = new BMapLib.DrawingManager(map, {
isOpen: false, //是否开启绘制模式
enableDrawingTool: true, //是否显示工具栏
drawingToolOptions: {
anchor: BMAP_ANCHOR_TOP_RIGHT, //位置
offset: new BMap.Size(5, 5), //偏离值
},
polygonOptions: styleOptions, //多边形的样式
});
//添加鼠标绘制工具监听事件,用于获取绘制结果
drawingManager.addEventListener('overlaycomplete', overlaycomplete);
var top_left_navigation = new BMap.NavigationControl(); //左上角,添加默认缩放平移控件
var top_left_control = new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT});// 左上角,添加比例尺
//添加控件和比例尺
map.addControl(top_left_navigation);
map.addControl(top_left_control);
$(document).ready(function(){
initTree("ztree_deliver", JSON.parse('${deliverTreeList}'));
queryOverlays();
});
//初始化加载
function queryOverlays(){
clearOverlays();
$.ajax({
url : 'queryGrids.do',
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
},
success : function(data) {
if(data != ""){
for(var i = 0; i < data.length; i ++){
var pointArray = new Array();
var entity = data[i];
var grids = JSON.parse(entity.ccoordinate);
for(var j = 0; j < grids.length; j ++){
pointArray[j] = new BMap.Point(grids[j].lng, grids[j].lat);
}
var polygon = new BMap.Polygon(pointArray, styleOptions);
//调用计算中心点方法 返回Point
var point = getCenterPointWithPolygon(pointArray);
var label = new BMap.Label(entity.deliverName,{offset: new BMap.Size(entity.deliverName.length * -9, 0),position:new BMap.Point(point.lng, point.lat)});
label.setStyle({
color : "#fff",
fontSize : "12px",
height : "20px",
lineHeight : "18px",
padding : "0px " + entity.deliverName.length * 13 + "px 2px 5px",
backgroundColor: "#2e8af1",
borderColor : "#2e8af1",
borderRadius : "5px",
});
polygon.deliverId = entity.deliverId;
polygon.cidstr = entity.cidstr;
polygon.label = label;
map.addOverlay(polygon);
map.addOverlay(label);
//防止没触发完成状态就点击保存
previousPoint = null;
firstPoint = null;
polygon_array = new Array();
drawingManager.close();
}
}
},
error : function(data) {
noty_info('加载失败', 'error');
return false;
}
});
}
//提交
function grid_submit(){
if($('#deliverId').val() == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
//需要校验是否有重叠,主要是修改的时候拖动覆盖物造成的
if(!graphicValid_update()){
return false;
}
var box = $("#BMap_submit_modal");
box.modal();
$("#submit_modal_ok").off();
$("#submit_modal_ok").on("click", function() {
var polygon_array = new Array();
var grids = "[";
for(var i = 0; i < overlays.length; i++){
var overlay = overlays[i].getPath();
var cid = overlays[i].cidstr;
polygon_array.push(overlays[i]);
if (typeof(cid) == "undefined" || cid == "") {
cid = "0";
}
grids += "{'cid':" + cid + ", 'ccoordinate':'[";
for(var j = 0; j < overlay.length; j++){
var grid = overlay[j];
if(j == 0){
grids += "{\"lat\":\"" + grid.lat + "\",\"lng\":\"" + grid.lng + "\"}";
}else{
grids += ",{\"lat\":\"" + grid.lat + "\",\"lng\":\"" + grid.lng + "\"}";
}
}
grids += "]'},";
}
if (grids.length > 1) {
grids = grids.substr(0, grids.length - 1);
}
grids += "]";
$.ajax({
url : 'saveGrids.do',
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
},
data : JSON.stringify({"deliverId" : $('#deliverId').val(), "grids" : grids}),
success : function(data) {
noty_info('保存成功', 'success');
//grid_update_cancel();
queryOverlays();
overlays = [];
},
error : function(data) {
noty_info('保存失败', 'error');
return false;
}
});
box.modal('hide');
});
}
//修改
function grid_update(){
var deliverId = $('#deliverId').val();
if(deliverId == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && deliverId == polygon.deliverId){
polygon.enableEditing();
polygon.addEventListener('lineupdate', update_overlays(polygon));
}
}
//关闭制图状态
drawingManager.close();
}
//编辑的时候将当前对象放入集合中
function update_overlays(polygon){
if(overlays.indexOf(polygon) == -1){
overlays.push(polygon);
}
}
//取消编辑状态
function grid_update_cancel(){
var deliverId = $('#deliverId').val();
if(deliverId == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && deliverId == polygon.deliverId){
polygon.disableEditing();
polygon.removeEventListener('lineupdate', update_overlays);
}
}
//打开
//drawingManager.open();
}
//删除
function grid_delete(){
var deliverId = $('#deliverId').val();
if(deliverId == ''){
noty_info("请选择揽投部信息", "error");
return false;
}
var box = $("#BMap_delete_modal");
box.modal();
$("#delete_modal_ok").off();
$("#delete_modal_ok").on("click", function() {
$.ajax({
url : 'deleteGrids.do',
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("Accept","application/json");
xhr.setRequestHeader("Content-Type","application/json");
},
data : deliverId,
success : function(data) {
deleteOverlays(deliverId);
noty_info('删除成功', 'success');
},
error : function(data) {
noty_info('删除失败', 'error');
return false;
}
});
box.modal('hide');
});
}
//删除地图上某个揽投部覆盖物
function deleteOverlays(deliverId){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && deliverId == polygon.deliverId){
map.removeOverlay(polygon);
map.removeOverlay(polygon.label);
}
}
overlays = [];
}
//清除地图上所有自定义覆盖物
function clearOverlays(){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]'){
map.removeOverlay(polygon);
map.removeOverlay(polygon.label);
}
}
}
//当前揽投部填充颜色切换
function changeOverlays(value, e){
//如果有修改未保存的数据需要弹窗提示
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
if(allOverlays[i].toString() == '[object Polygon]'){
var polygon = allOverlays[i];
polygon.removeEventListener('lineupdate', update_overlays);
polygon.disableEditing();
if(value == polygon.deliverId){
polygon.setFillColor("#ada5aa");
var zoom = map.getZoom();
map.setViewport(polygon.getPath());
map.setZoom(zoom);
}else{
polygon.setFillColor("white");
}
}
}
drawingManager.close();
//切换下拉框后清除页面所有操作元素
overlays = [];
}
//图形校验(1、图形与图形的关系, 以及之前的图形和当前点的关系)
function graphicValid(point){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && typeof(polygon.deliverId) != "undefined"){
if(previousPoint != null){
var result = isLineCrossPolygon(previousPoint, point, polygon.getPath());
if(result){
noty_info("揽投部区域重叠", "error");
return false;
}
}else{
//此判断能防止先画大圈后画小圈的问题(覆盖物重叠)
var result = BMapLib.GeoUtils.isPointInPolygon(point, polygon);
if(result){
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
return true
}
//判断先画小圈再画大圈的情况
function graphicOverlap(point){
polygon_array.push(point);
if(polygon_array.length >= 3){
var polygon = new BMap.Polygon(polygon_array, styleOptions);
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
if(allOverlays[i].toString() == '[object Polygon]' && typeof(allOverlays[i].deliverId) != "undefined"){
var overlay = allOverlays[i].getPath();
for(var j = 0; j < overlay.length; j ++){
var old_point = overlay[j];
var result = BMapLib.GeoUtils.isPointInPolygon(old_point, polygon);
if(result){
//如果是重叠的,那么要删除当前polygon_array的点
var index = polygon_array.indexOf(point);
if(index > -1){
polygon_array.splice(index, 1);
}
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
}
if(firstPoint == null){
firstPoint = point;
}
previousPoint = point;
return true;
}
//完成时判断最后一点和第一个点连线
function overlaycompleteValid(point){
var allOverlays = map.getOverlays();
for(var i = 0; i < allOverlays.length; i++){
var polygon = allOverlays[i];
if(polygon.toString() == '[object Polygon]' && typeof(polygon.deliverId) != "undefined"){
if(previousPoint != null){
var result = isLineCrossPolygon(firstPoint, point, polygon.getPath());
if(result){
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
return true
}
//图形校验(判断更改后是否有图形重叠)
function graphicValid_update() {
var allOverlays = map.getOverlays();
for (var i = 0; i < overlays.length; i ++) {
var overlay = overlays[i].getPath();
for (var k = 0; k < allOverlays.length; k ++) {
var polygon = allOverlays[k];
if(polygon == overlays[i] || polygon.toString() != '[object Polygon]'){
continue;
}
for (var j = 0; j < overlay.length - 1; j ++) {
var point1 = overlay[j];
var point2 = overlay[j + 1];
var result = isLineCrossPolygon(point1, point2, polygon.getPath());
if (result) {
noty_info("揽投部区域重叠", "error");
return false;
}
}
}
}
return true
}
//打开绘图工具事件
function drawing_onclick(e) {
if ($('#deliverId').val() == '') {
if (e && e.stopPropagation) {
//因此它支持W3C的stopPropagation()方法
e.preventDefault();
e.stopPropagation();
} else {
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
noty_info("请选择揽投部信息", "error");
}
}
function noty_info(text, type) {
noty({
text : text,
layout : 'center',
type : type,
timeout : 2000
});
}
</script>
</body>
</html>
js
var setting = {
view : {
dblClickExpand : false,
selectedMulti : false
},
data : {
simpleData : {
enable : true,
idKey : "strId",
pIdKey : "strParentid"
},
key : {
name : "cname"
}
},
callback : {
beforeClick : beforeClick,
onClick : onClick
}
};
function initTree(treeid, zNodes) {
var newNode = {
strId : 0,
cname : "揽投部"
};
zNodes.push(newNode);
var treeObj = $.fn.zTree.init($("#" + treeid), setting, zNodes);
treeObj.expandAll(true);
}
function beforeClick(treeId, treeNode) {
var check = (treeNode && !treeNode.isParent);
if (!check){
noty_info("只能选择子节点...", "error");
}
return check;
}
function onClick(e, treeId, treeNode) {
var zTree = $.fn.zTree.getZTreeObj("ztree_deliver");
var nodes = zTree.getSelectedNodes();
$("#deliverName").val(nodes[0].cname);
$("#deliverId").val(nodes[0].strId);
changeOverlays(nodes[0].strId);
hideMenu();
}
function deliver_onfocus(value){
showMenu();
if(value != ""){
var zTree = $.fn.zTree.getZTreeObj("ztree_deliver");
var shownodes = zTree.getNodesByParam("isHidden", true);
zTree.showNodes(shownodes);
var deliverId = $("#deliverId").val();
if(deliverId != ""){
//根据Id高亮显示上一次选择树
var nodes = zTree.transformToArray(zTree.getNodes());
for(var i = 0 ; i < nodes.length; i ++){
if(nodes[i].strId == deliverId){
nodes[i].highlight = true;
zTree.updateNode(nodes[i]);
}
}
}
}
}
function deliver_oninput(value){
//树的过滤
var zTree = $.fn.zTree.getZTreeObj("ztree_deliver");
var shownodes = zTree.getNodesByParam("isHidden", true);
zTree.showNodes(shownodes);
zTree.getNodesByFilter(nodeFilter(zTree, value));
}
function nodeFilter(zTree, value){
var showNodes = new Array();
var allNodes = zTree.transformToArray(zTree.getNodes());
zTree.hideNodes(allNodes);
for(var i = 0 ; i < allNodes.length; i ++){
if(allNodes[i].cname.indexOf(value) >= 0){
showNodes.push(allNodes[i]);
}
}
if(showNodes.length == 0){
return false;
}
var resultNodes = new Array();
for(var i = 0; i < showNodes.length; i ++){
getParentNode(showNodes[i], resultNodes);
}
zTree.showNodes(resultNodes);
zTree.expandAll(true);
}
function getParentNode(node, resultNodes) {
if (node != null && node != "") {
resultNodes.push(node);
var parentNode = node.getParentNode();
return getParentNode(parentNode, resultNodes);
} else {
return;
}
}
function showMenu() {
$("#menuContent").slideDown("fast");
$("body").bind("mousedown", onBodyDown);
}
function hideMenu() {
$("#menuContent").fadeOut("fast");
$("body").unbind("mousedown", onBodyDown);
}
function onBodyDown(event) {
if (!(event.target.id == "menuBtn" || event.target.id == "menuContent" || $(event.target).parents("#menuContent").length > 0)) {
hideMenu();
$("#deliverName").blur();
}
}
/**
* @fileoverview 百度地图的鼠标绘制工具,对外开放。
* 允许用户在地图上点击完成鼠标绘制的功能。
* 使用者可以自定义所绘制结果的相关样式,例如线宽、颜色、测线段距离、面积等等。
* 主入口类是<a href="symbols/BMapLib.DrawingManager.html">DrawingManager</a>,
* 基于Baidu Map API 1.4。
*
* @author Baidu Map Api Group
* @version 1.4
*/
/**
* @namespace BMap的所有library类均放在BMapLib命名空间下
*/
var BMapLib = window.BMapLib = BMapLib || {};
/**
* 定义常量, 绘制的模式
* @final {Number} DrawingType
*/
var BMAP_DRAWING_MARKER = "marker", // 鼠标画点模式
BMAP_DRAWING_POLYLINE = "polyline", // 鼠标画线模式
BMAP_DRAWING_CIRCLE = "circle", // 鼠标画圆模式
BMAP_DRAWING_RECTANGLE = "rectangle", // 鼠标画矩形模式
BMAP_DRAWING_POLYGON = "polygon"; // 鼠标画多边形模式
(function() {
/**
* 声明baidu包
*/
var baidu = baidu || {guid : "$BAIDU$"};
(function() {
// 一些页面级别唯一的属性,需要挂载在window[baidu.guid]上
window[baidu.guid] = {};
/**
* 将源对象的所有属性拷贝到目标对象中
* @name baidu.extend
* @function
* @grammar baidu.extend(target, source)
* @param {Object} target 目标对象
* @param {Object} source 源对象
* @returns {Object} 目标对象
*/
baidu.extend = function (target, source) {
for (var p in source) {
if (source.hasOwnProperty(p)) {
target[p] = source[p];
}
}
return target;
};
/**
* @ignore
* @namespace
* @baidu.lang 对语言层面的封装,包括类型判断、模块扩展、继承基类以及对象自定义事件的支持。
* @property guid 对象的唯一标识
*/
baidu.lang = baidu.lang || {};
/**
* 返回一个当前页面的唯一标识字符串。
* @function
* @grammar baidu.lang.guid()
* @returns {String} 当前页面的唯一标识字符串
*/
baidu.lang.guid = function() {
return "TANGRAM__" + (window[baidu.guid]._counter ++).toString(36);
};
window[baidu.guid]._counter = window[baidu.guid]._counter || 1;
/**
* 所有类的实例的容器
* key为每个实例的guid
*/
window[baidu.guid]._instances = window[baidu.guid]._instances || {};
/**
* Tangram继承机制提供的一个基类,用户可以通过继承baidu.lang.Class来获取它的属性及方法。
* @function
* @name baidu.lang.Class
* @grammar baidu.lang.Class(guid)
* @param {string} guid 对象的唯一标识
* @meta standard
* @remark baidu.lang.Class和它的子类的实例均包含一个全局唯一的标识guid。
* guid是在构造函数中生成的,因此,继承自baidu.lang.Class的类应该直接或者间接调用它的构造函数。<br>
* baidu.lang.Class的构造函数中产生guid的方式可以保证guid的唯一性,及每个实例都有一个全局唯一的guid。
*/
baidu.lang.Class = function(guid) {
this.guid = guid || baidu.lang.guid();
window[baidu.guid]._instances[this.guid] = this;
};
window[baidu.guid]._instances = window[baidu.guid]._instances || {};
/**
* 判断目标参数是否string类型或String对象
* @name baidu.lang.isString
* @function
* @grammar baidu.lang.isString(source)
* @param {Any} source 目标参数
* @shortcut isString
* @meta standard
*
* @returns {boolean} 类型判断结果
*/
baidu.lang.isString = function (source) {
return '[object String]' == Object.prototype.toString.call(source);
};
/**
* 判断目标参数是否为function或Function实例
* @name baidu.lang.isFunction
* @function
* @grammar baidu.lang.isFunction(source)
* @param {Any} source 目标参数
* @returns {boolean} 类型判断结果
*/
baidu.lang.isFunction = function (source) {
return '[object Function]' == Object.prototype.toString.call(source);
};
/**
* 重载了默认的toString方法,使得返回信息更加准确一些。
* @return {string} 对象的String表示形式
*/
baidu.lang.Class.prototype.toString = function(){
return "[object " + (this._className || "Object" ) + "]";
};
/**
* 释放对象所持有的资源,主要是自定义事件。
* @name dispose
* @grammar obj.dispose()
*/
baidu.lang.Class.prototype.dispose = function(){
delete window[baidu.guid]._instances[this.guid];
for(var property in this){
if (!baidu.lang.isFunction(this[property])) {
delete this[property];
}
}
this.disposed = true;
};
/**
* 自定义的事件对象。
* @function
* @name baidu.lang.Event
* @grammar baidu.lang.Event(type[, target])
* @param {string} type 事件类型名称。为了方便区分事件和一个普通的方法,事件类型名称必须以"on"(小写)开头。
* @param {Object} [target]触发事件的对象
* @meta standard
* @remark 引入该模块,会自动为Class引入3个事件扩展方法:addEventListener、removeEventListener和dispatchEvent。
* @see baidu.lang.Class
*/
baidu.lang.Event = function (type, target) {
this.type = type;
this.returnValue = true;
this.target = target || null;
this.currentTarget = null;
};
/**
* 注册对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
* @grammar obj.addEventListener(type, handler[, key])
* @param {string} type 自定义事件的名称
* @param {Function} handler 自定义事件被触发时应该调用的回调函数
* @param {string} [key] 为事件监听函数指定的名称,可在移除时使用。如果不提供,方法会默认为它生成一个全局唯一的key。
* @remark 事件类型区分大小写。如果自定义事件名称不是以小写"on"开头,该方法会给它加上"on"再进行判断,即"click"和"onclick"会被认为是同一种事件。
*/
baidu.lang.Class.prototype.addEventListener = function (type, handler, key) {
if (!baidu.lang.isFunction(handler)) {
return;
}
!this.__listeners && (this.__listeners = {});
var t = this.__listeners, id;
if (typeof key == "string" && key) {
if (/[^\w\-]/.test(key)) {
throw("nonstandard key:" + key);
} else {
handler.hashCode = key;
id = key;
}
}
type.indexOf("on") != 0 && (type = "on" + type);
typeof t[type] != "object" && (t[type] = {});
id = id || baidu.lang.guid();
handler.hashCode = id;
t[type][id] = handler;
};
/**
* 移除对象的事件监听器。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
* @grammar obj.removeEventListener(type, handler)
* @param {string} type 事件类型
* @param {Function|string} handler 要移除的事件监听函数或者监听函数的key
* @remark 如果第二个参数handler没有被绑定到对应的自定义事件中,什么也不做。
*/
baidu.lang.Class.prototype.removeEventListener = function (type, handler) {
if (baidu.lang.isFunction(handler)) {
handler = handler.hashCode;
} else if (!baidu.lang.isString(handler)) {
return;
}
!this.__listeners && (this.__listeners = {});
type.indexOf("on") != 0 && (type = "on" + type);
var t = this.__listeners;
if (!t[type]) {
return;
}
t[type][handler] && delete t[type][handler];
};
/**
* 派发自定义事件,使得绑定到自定义事件上面的函数都会被执行。引入baidu.lang.Event后,Class的子类实例才会获得该方法。
* @grammar obj.dispatchEvent(event, options)
* @param {baidu.lang.Event|String} event Event对象,或事件名称(1.1.1起支持)
* @param {Object} options 扩展参数,所含属性键值会扩展到Event对象上(1.2起支持)
* @remark 处理会调用通过addEventListenr绑定的自定义事件回调函数之外,还会调用直接绑定到对象上面的自定义事件。
* 例如:<br>
* myobj.onMyEvent = function(){}<br>
* myobj.addEventListener("onMyEvent", function(){});
*/
baidu.lang.Class.prototype.dispatchEvent = function (event, options) {
if (baidu.lang.isString(event)) {
event = new baidu.lang.Event(event);
}
!this.__listeners && (this.__listeners = {});
options = options || {};
for (var i in options) {
event[i] = options[i];
}
var i, t = this.__listeners, p = event.type;
event.target = event.target || this;
event.currentTarget = this;
p.indexOf("on") != 0 && (p = "on" + p);
baidu.lang.isFunction(this[p]) && this[p].apply(this, arguments);
if (typeof t[p] == "object") {
for (i in t[p]) {
t[p][i].apply(this, arguments);
}
}
return event.returnValue;
};
/**
* 为类型构造器建立继承关系
* @name baidu.lang.inherits
* @function
* @grammar baidu.lang.inherits(subClass, superClass[, className])
* @param {Function} subClass 子类构造器
* @param {Function} superClass 父类构造器
* @param {string} className 类名标识
* @remark 使subClass继承superClass的prototype,
* 因此subClass的实例能够使用superClass的prototype中定义的所有属性和方法。<br>
* 这个函数实际上是建立了subClass和superClass的原型链集成,并对subClass进行了constructor修正。<br>
* <strong>注意:如果要继承构造函数,需要在subClass里面call一下,具体见下面的demo例子</strong>
* @shortcut inherits
* @meta standard
* @see baidu.lang.Class
*/
baidu.lang.inherits = function (subClass, superClass, className) {
var key, proto,
selfProps = subClass.prototype,
clazz = new Function();
clazz.prototype = superClass.prototype;
proto = subClass.prototype = new clazz();
for (key in selfProps) {
proto[key] = selfProps[key];
}
subClass.prototype.constructor = subClass;
subClass.superClass = superClass.prototype;
if ("string" == typeof className) {
proto._className = className;
}
};
/**
* @ignore
* @namespace baidu.dom 操作dom的方法。
*/
baidu.dom = baidu.dom || {};
/**
* 从文档中获取指定的DOM元素
*
* @param {string|HTMLElement} id 元素的id或DOM元素
* @meta standard
* @return {HTMLElement} DOM元素,如果不存在,返回null,如果参数不合法,直接返回参数
*/
baidu._g = baidu.dom._g = function (id) {
if (baidu.lang.isString(id)) {
return document.getElementById(id);
}
return id;
};
/**
* 从文档中获取指定的DOM元素
* @name baidu.dom.g
* @function
* @grammar baidu.dom.g(id)
* @param {string|HTMLElement} id 元素的id或DOM元素
* @meta standard
*
* @returns {HTMLElement|null} 获取的元素,查找不到时返回null,如果参数不合法,直接返回参数
*/
baidu.g = baidu.dom.g = function (id) {
if ('string' == typeof id || id instanceof String) {
return document.getElementById(id);
} else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
return id;
}
return null;
};
/**
* 在目标元素的指定位置插入HTML代码
* @name baidu.dom.insertHTML
* @function
* @grammar baidu.dom.insertHTML(element, position, html)
* @param {HTMLElement|string} element 目标元素或目标元素的id
* @param {string} position 插入html的位置信息,取值为beforeBegin,afterBegin,beforeEnd,afterEnd
* @param {string} html 要插入的html
* @remark
*
* 对于position参数,大小写不敏感<br>
* 参数的意思:beforeBegin<span>afterBegin this is span! beforeEnd</span> afterEnd <br />
* 此外,如果使用本函数插入带有script标签的HTML字符串,script标签对应的脚本将不会被执行。
*
* @shortcut insertHTML
* @meta standard
*
* @returns {HTMLElement} 目标元素
*/
baidu.insertHTML = baidu.dom.insertHTML = function (element, position, html) {
element = baidu.dom.g(element);
var range,begin;
if (element.insertAdjacentHTML) {
element.insertAdjacentHTML(position, html);
} else {
// 这里不做"undefined" != typeof(HTMLElement) && !window.opera判断,其它浏览器将出错?!
// 但是其实做了判断,其它浏览器下等于这个函数就不能执行了
range = element.ownerDocument.createRange();
// FF下range的位置设置错误可能导致创建出来的fragment在插入dom树之后html结构乱掉
// 改用range.insertNode来插入html, by wenyuxiang @ 2010-12-14.
position = position.toUpperCase();
if (position == 'AFTERBEGIN' || position == 'BEFOREEND') {
range.selectNodeContents(element);
range.collapse(position == 'AFTERBEGIN');
} else {
begin = position == 'BEFOREBEGIN';
range[begin ? 'setStartBefore' : 'setEndAfter'](element);
range.collapse(begin);
}
range.insertNode(range.createContextualFragment(html));
}
return element;
};
/**
* 为目标元素添加className
* @name baidu.dom.addClass
* @function
* @grammar baidu.dom.addClass(element, className)
* @param {HTMLElement|string} element 目标元素或目标元素的id
* @param {string} className 要添加的className,允许同时添加多个class,中间使用空白符分隔
* @remark
* 使用者应保证提供的className合法性,不应包含不合法字符,className合法字符参考:http://www.w3.org/TR/CSS2/syndata.html。
* @shortcut addClass
* @meta standard
*
* @returns {HTMLElement} 目标元素
*/
baidu.ac = baidu.dom.addClass = function (element, className) {
element = baidu.dom.g(element);
var classArray = className.split(/\s+/),
result = element.className,
classMatch = " " + result + " ",
i = 0,
l = classArray.length;
for (; i < l; i++){
if ( classMatch.indexOf( " " + classArray[i] + " " ) < 0 ) {
result += (result ? ' ' : '') + classArray[i];
}
}
element.className = result;
return element;
};
/**
* @ignore
* @namespace baidu.event 屏蔽浏览器差异性的事件封装。
* @property target 事件的触发元素
* @property pageX 鼠标事件的鼠标x坐标
* @property pageY 鼠标事件的鼠标y坐标
* @property keyCode 键盘事件的键值
*/
baidu.event = baidu.event || {};
/**
* 事件监听器的存储表
* @private
* @meta standard
*/
baidu.event._listeners = baidu.event._listeners || [];
/**
* 为目标元素添加事件监听器
* @name baidu.event.on
* @function
* @grammar baidu.event.on(element, type, listener)
* @param {HTMLElement|string|window} element 目标元素或目标元素id
* @param {string} type 事件类型
* @param {Function} listener 需要添加的监听器
* @remark
* 1. 不支持跨浏览器的鼠标滚轮事件监听器添加<br>
* 2. 改方法不为监听器灌入事件对象,以防止跨iframe事件挂载的事件对象获取失败
* @shortcut on
* @meta standard
* @see baidu.event.un
*
* @returns {HTMLElement|window} 目标元素
*/
baidu.on = baidu.event.on = function (element, type, listener) {
type = type.replace(/^on/i, '');
element = baidu._g(element);
var realListener = function (ev) {
// 1. 这里不支持EventArgument, 原因是跨frame的事件挂载
// 2. element是为了修正this
listener.call(element, ev);
},
lis = baidu.event._listeners,
filter = baidu.event._eventFilter,
afterFilter,
realType = type;
type = type.toLowerCase();
// filter过滤
if(filter && filter[type]){
afterFilter = filter[type](element, type, realListener);
realType = afterFilter.type;
realListener = afterFilter.listener;
}
// 事件监听器挂载
if (element.addEventListener) {
element.addEventListener(realType, realListener, false);
} else if (element.attachEvent) {
element.attachEvent('on' + realType, realListener);
}
// 将监听器存储到数组中
lis[lis.length] = [element, type, listener, realListener, realType];
return element;
};
/**
* 为目标元素移除事件监听器
* @name baidu.event.un
* @function
* @grammar baidu.event.un(element, type, listener)
* @param {HTMLElement|string|window} element 目标元素或目标元素id
* @param {string} type 事件类型
* @param {Function} listener 需要移除的监听器
* @shortcut un
* @meta standard
*
* @returns {HTMLElement|window} 目标元素
*/
baidu.un = baidu.event.un = function (element, type, listener) {
element = baidu._g(element);
type = type.replace(/^on/i, '').toLowerCase();
var lis = baidu.event._listeners,
len = lis.length,
isRemoveAll = !listener,
item,
realType, realListener;
//如果将listener的结构改成json
//可以节省掉这个循环,优化性能
//但是由于un的使用频率并不高,同时在listener不多的时候
//遍历数组的性能消耗不会对代码产生影响
//暂不考虑此优化
while (len--) {
item = lis[len];
// listener存在时,移除element的所有以listener监听的type类型事件
// listener不存在时,移除element的所有type类型事件
if (item[1] === type
&& item[0] === element
&& (isRemoveAll || item[2] === listener)) {
realType = item[4];
realListener = item[3];
if (element.removeEventListener) {
element.removeEventListener(realType, realListener, false);
} else if (element.detachEvent) {
element.detachEvent('on' + realType, realListener);
}
lis.splice(len, 1);
}
}
return element;
};
/**
* 获取event事件,解决不同浏览器兼容问题
* @param {Event}
* @return {Event}
*/
baidu.getEvent = baidu.event.getEvent = function (event) {
return window.event || event;
}
/**
* 获取event.target,解决不同浏览器兼容问题
* @param {Event}
* @return {Target}
*/
baidu.getTarget = baidu.event.getTarget = function (event) {
var event = baidu.getEvent(event);
return event.target || event.srcElement;
}
/**
* 阻止事件的默认行为
* @name baidu.event.preventDefault
* @function
* @grammar baidu.event.preventDefault(event)
* @param {Event} event 事件对象
* @meta standard
*/
baidu.preventDefault = baidu.event.preventDefault = function (event) {
var event = baidu.getEvent(event);
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
};
/**
* 停止事件冒泡传播
* @param {Event}
*/
baidu.stopBubble = baidu.event.stopBubble = function (event) {
event = baidu.getEvent(event);
event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
}
})();
/**
* @exports DrawingManager as BMapLib.DrawingManager
*/
var DrawingManager =
/**
* DrawingManager类的构造函数
* @class 鼠标绘制管理类,实现鼠标绘制管理的<b>入口</b>。
* 实例化该类后,即可调用该类提供的open
* 方法开启绘制模式状态。
* 也可加入工具栏进行选择操作。
*
* @constructor
* @param {Map} map Baidu map的实例对象
* @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br />
* {"<b>isOpen</b>" : {Boolean} 是否开启绘制模式
* <br />"<b>enableDrawingTool</b>" : {Boolean} 是否添加绘制工具栏控件,默认不添加
* <br />"<b>drawingToolOptions</b>" : {Json Object} 可选的输入参数,非必填项。可输入选项包括
* <br /> "<b>anchor</b>" : {ControlAnchor} 停靠位置、默认左上角
* <br /> "<b>offset</b>" : {Size} 偏移值。
* <br /> "<b>scale</b>" : {Number} 工具栏的缩放比例,默认为1
* <br /> "<b>drawingModes</b>" : {DrawingType<Array>} 工具栏上可以选择出现的绘制模式,将需要显示的DrawingType以数组型形式传入,如[BMAP_DRAWING_MARKER, BMAP_DRAWING_CIRCLE] 将只显示画点和画圆的选项
* <br />"<b>enableCalculate</b>" : {Boolean} 绘制是否进行测距(画线时候)、测面(画圆、多边形、矩形)
* <br />"<b>markerOptions</b>" : {CircleOptions} 所画的点的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>circleOptions</b>" : {CircleOptions} 所画的圆的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>polylineOptions</b>" : {CircleOptions} 所画的线的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>polygonOptions</b>" : {PolygonOptions} 所画的多边形的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
* <br />"<b>rectangleOptions</b>" : {PolygonOptions} 所画的矩形的可选参数,参考api中的<a href="http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E8%A6%86%E7%9B%96%E7%89%A9%E7%B1%BB">对应类</a>
*
* @example <b>参考示例:</b><br />
* var map = new BMap.Map("container");<br />map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);<br />
* var myDrawingManagerObject = new BMapLib.DrawingManager(map, {isOpen: true,
* drawingType: BMAP_DRAWING_MARKER, enableDrawingTool: true,
* enableCalculate: false,
* drawingToolOptions: {
* anchor: BMAP_ANCHOR_TOP_LEFT,
* offset: new BMap.Size(5, 5),
* drawingTypes : [
* BMAP_DRAWING_MARKER,
* BMAP_DRAWING_CIRCLE,
* BMAP_DRAWING_POLYLINE,
* BMAP_DRAWING_POLYGON,
* BMAP_DRAWING_RECTANGLE
* ]
* },
* polylineOptions: {
* strokeColor: "#333"
* });
*/
BMapLib.DrawingManager = function(map, opts){
if (!map) {
return;
}
instances.push(this);
opts = opts || {};
this._initialize(map, opts);
}
// 通过baidu.lang下的inherits方法,让DrawingManager继承baidu.lang.Class
baidu.lang.inherits(DrawingManager, baidu.lang.Class, "DrawingManager");
/**
* 开启地图的绘制模式
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.open();
*/
DrawingManager.prototype.open = function() {
// 判断绘制状态是否已经开启
if (this._isOpen == true){
return true;
}
closeInstanceExcept(this);
this._open();
}
/**
* 关闭地图的绘制状态
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.close();
*/
DrawingManager.prototype.close = function() {
// 判断绘制状态是否已经开启
if (this._isOpen == false){
return true;
}
this._close();
}
/**
* 设置当前的绘制模式,参数DrawingType,为5个可选常量:
* <br/>BMAP_DRAWING_MARKER 画点
* <br/>BMAP_DRAWING_CIRCLE 画圆
* <br/>BMAP_DRAWING_POLYLINE 画线
* <br/>BMAP_DRAWING_POLYGON 画多边形
* <br/>BMAP_DRAWING_RECTANGLE 画矩形
* @param {DrawingType} DrawingType
* @return {Boolean}
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.setDrawingMode(BMAP_DRAWING_POLYLINE);
*/
DrawingManager.prototype.setDrawingMode = function(drawingType) {
//与当前模式不一样时候才进行重新绑定事件
if (this._drawingType != drawingType) {
closeInstanceExcept(this);
this._setDrawingMode(drawingType);
}
}
/**
* 获取当前的绘制模式
* @return {DrawingType} 绘制的模式
*
* @example <b>参考示例:</b><br />
* alert(myDrawingManagerObject.getDrawingMode());
*/
DrawingManager.prototype.getDrawingMode = function() {
return this._drawingType;
}
/**
* 打开距离或面积计算
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.enableCalculate();
*/
DrawingManager.prototype.enableCalculate = function() {
this._enableCalculate = true;
this._addGeoUtilsLibrary();
}
/**
* 关闭距离或面积计算
*
* @example <b>参考示例:</b><br />
* myDrawingManagerObject.disableCalculate();
*/
DrawingManager.prototype.disableCalculate = function() {
this._enableCalculate = false;
}
/**
* 鼠标绘制完成后,派发总事件的接口
* @name DrawingManager#overlaycomplete
* @event
* @param {Event Object} e 回调函数会返回event参数,包括以下返回值:
* <br />{"<b>drawingMode</b> : {DrawingType} 当前的绘制模式
* <br />"<b>overlay</b>:{Marker||Polyline||Polygon||Circle} 对应的绘制模式返回对应的覆盖物
* <br />"<b>calculate</b>:{Number} 需要开启计算模式才会返回这个值,当绘制线的时候返回距离、绘制多边形、圆、矩形时候返回面积,单位为米,
* <br />"<b>label</b>:{Label} 计算面积时候出现在Map上的Label对象
*
* @example <b>参考示例:</b>
* myDrawingManagerObject.addEventListener("overlaycomplete", function(e) {
* alert(e.drawingMode);
* alert(e.overlay);
* alert(e.calculate);
* alert(e.label);
* });
*/
/**
* 绘制点完成后,派发的事件接口
* @name DrawingManager#markercomplete
* @event
* @param {Marker} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Marker}
*
* @example <b>参考示例:</b>
* myDrawingManagerObject.addEventListener("circlecomplete", function(e, overlay) {
* alert(overlay);
* });
*/
/**
* 绘制圆完成后,派发的事件接口
* @name DrawingManager#circlecomplete
* @event
* @param {Circle} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Circle}
*/
/**
* 绘制线完成后,派发的事件接口
* @name DrawingManager#polylinecomplete
* @event
* @param {Polyline} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Polyline}
*/
/**
* 绘制多边形完成后,派发的事件接口
* @name DrawingManager#polygoncomplete
* @event
* @param {Polygon} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Polygon}
*/
/**
* 绘制矩形完成后,派发的事件接口
* @name DrawingManager#rectanglecomplete
* @event
* @param {Polygon} overlay 回调函数会返回相应的覆盖物,
* <br />{"<b>overlay</b> : {Polygon}
*/
/**
* 初始化状态
* @param {Map} 地图实例
* @param {Object} 参数
*/
DrawingManager.prototype._initialize = function(map, opts) {
/**
* map对象
* @private
* @type {Map}
*/
this._map = map;
/**
* 配置对象
* @private
* @type {Object}
*/
this._opts = opts;
/**
* 当前的绘制模式, 默认是绘制点
* @private
* @type {DrawingType}
*/
this._drawingType = opts.drawingMode || BMAP_DRAWING_MARKER;
/**
* 是否添加添加鼠标绘制工具栏面板
*/
if (opts.enableDrawingTool) {
var drawingTool = new DrawingTool(this, opts.drawingToolOptions);
this._drawingTool = drawingTool;
map.addControl(drawingTool);
}
//是否计算绘制出的面积
if (opts.enableCalculate === true) {
this.enableCalculate();
} else {
this.disableCalculate();
}
/**
* 是否已经开启了绘制状态
* @private
* @type {Boolean}
*/
this._isOpen = !!(opts.isOpen === true);
if (this._isOpen) {
this._open();
}
this.markerOptions = opts.markerOptions || {};
this.circleOptions = opts.circleOptions || {};
this.polylineOptions = opts.polylineOptions || {};
this.polygonOptions = opts.polygonOptions || {};
this.rectangleOptions = opts.rectangleOptions || {};
},
/**
* 开启地图的绘制状态
* @return {Boolean},开启绘制状态成功,返回true;否则返回false。
*/
DrawingManager.prototype._open = function() {
this._isOpen = true;
//添加遮罩,所有鼠标操作都在这个遮罩上完成
if (!this._mask) {
this._mask = new Mask();
}
this._map.addOverlay(this._mask);
this._setDrawingMode(this._drawingType);
}
/**
* 设置当前的绘制模式
* @param {DrawingType}
*/
DrawingManager.prototype._setDrawingMode = function(drawingType) {
this._drawingType = drawingType;
/**
* 开启编辑状态时候才重新进行事件绑定
*/
if (this._isOpen) {
//清空之前的自定义事件
this._mask.__listeners = {};
switch (drawingType) {
case BMAP_DRAWING_MARKER:
this._bindMarker();
break;
case BMAP_DRAWING_CIRCLE:
this._bindCircle();
break;
case BMAP_DRAWING_POLYLINE:
case BMAP_DRAWING_POLYGON:
this._bindPolylineOrPolygon();
break;
case BMAP_DRAWING_RECTANGLE:
this._bindRectangle();
break;
}
}
/**
* 如果添加了工具栏,则也需要改变工具栏的样式
*/
if (this._drawingTool && this._isOpen) {
this._drawingTool.setStyleByDrawingMode(drawingType);
}
}
/**
* 关闭地图的绘制状态
* @return {Boolean},关闭绘制状态成功,返回true;否则返回false。
*/
DrawingManager.prototype._close = function() {
this._isOpen = false;
if (this._mask) {
this._map.removeOverlay(this._mask);
}
/**
* 如果添加了工具栏,则关闭时候将工具栏样式设置为拖拽地图
*/
if (this._drawingTool) {
this._drawingTool.setStyleByDrawingMode("hander");
}
}
/**
* 绑定鼠标画点的事件
*/
DrawingManager.prototype._bindMarker = function() {
var me = this,
map = this._map,
mask = this._mask;
/**
* 鼠标点击的事件
*/
var clickAction = function (e) {
// 往地图上添加marker
var marker = new BMap.Marker(e.point, me.markerOptions);
map.addOverlay(marker);
me._dispatchOverlayComplete(marker);
}
mask.addEventListener('click', clickAction);
}
/**
* 绑定鼠标画圆的事件
*/
DrawingManager.prototype._bindCircle = function() {
var me = this,
map = this._map,
mask = this._mask,
circle = null,
centerPoint = null; //圆的中心点
/**
* 开始绘制圆形
*/
var startAction = function (e) {
centerPoint = e.point;
circle = new BMap.Circle(centerPoint, 0, me.circleOptions);
map.addOverlay(circle);
mask.enableEdgeMove();
mask.addEventListener('mousemove', moveAction);
baidu.on(document, 'mouseup', endAction);
}
/**
* 绘制圆形过程中,鼠标移动过程的事件
*/
var moveAction = function(e) {
circle.setRadius(me._map.getDistance(centerPoint, e.point));
}
/**
* 绘制圆形结束
*/
var endAction = function (e) {
var calculate = me._calculate(circle, e.point);
me._dispatchOverlayComplete(circle, calculate);
centerPoint = null;
mask.disableEdgeMove();
mask.removeEventListener('mousemove', moveAction);
baidu.un(document, 'mouseup', endAction);
}
/**
* 鼠标点击起始点
*/
var mousedownAction = function (e) {
baidu.preventDefault(e);
baidu.stopBubble(e);
if (centerPoint == null) {
startAction(e);
}
}
mask.addEventListener('mousedown', mousedownAction);
}
/**
* 画线和画多边形相似性比较大,公用一个方法
*/
DrawingManager.prototype._bindPolylineOrPolygon = function() {
var me = this,
map = this._map,
mask = this._mask,
points = [], //用户绘制的点
drawPoint = null; //实际需要画在地图上的点
overlay = null,
isBinded = false;
/**
* 鼠标点击的事件
*/
var startAction = function (e) {
//校验当前点是否合法
var valid_result = graphicValid(e.point);
//var over_result = overlaycompleteValid(e.point);
if(valid_result){
var overlap_valid = graphicOverlap(e.point);
if(overlap_valid){
points.push(e.point);
drawPoint = points.concat(points[points.length - 1]);
if (points.length == 1) {
if (me._drawingType == BMAP_DRAWING_POLYLINE) {
overlay = new BMap.Polyline(drawPoint, me.polylineOptions);
} else if (me._drawingType == BMAP_DRAWING_POLYGON) {
overlay = new BMap.Polygon(drawPoint, me.polygonOptions);
}
map.addOverlay(overlay);
} else {
overlay.setPath(drawPoint);
}
if (!isBinded) {
isBinded = true;
mask.enableEdgeMove();
mask.addEventListener('mousemove', mousemoveAction);
mask.addEventListener('dblclick', dblclickAction);
}
}
}
}
/**
* 鼠标移动过程的事件
*/
var mousemoveAction = function(e) {
overlay.setPositionAt(drawPoint.length - 1, e.point);
}
/**
* 鼠标双击的事件
*/
var dblclickAction = function (e) {
var over_result = overlaycompleteValid(e.point);
if(over_result){
baidu.stopBubble(e);
isBinded = false;
mask.disableEdgeMove();
mask.removeEventListener('mousemove', mousemoveAction);
mask.removeEventListener('dblclick', dblclickAction);
overlay.setPath(points);
var calculate = me._calculate(overlay, points.pop());
me._dispatchOverlayComplete(overlay, calculate);
points.length = 0;
drawPoint.length = 0;
}
}
mask.addEventListener('click', startAction);
//双击时候不放大地图级别
mask.addEventListener('dblclick', function(e){
baidu.stopBubble(e);
});
}
/**
* 绑定鼠标画矩形的事件
*/
DrawingManager.prototype._bindRectangle = function() {
var me = this,
map = this._map,
mask = this._mask,
polygon = null,
startPoint = null;
/**
* 开始绘制矩形
*/
var startAction = function (e) {
baidu.stopBubble(e);
baidu.preventDefault(e);
startPoint = e.point;
var endPoint = startPoint;
polygon = new BMap.Polygon(me._getRectanglePoint(startPoint, endPoint), me.rectangleOptions);
map.addOverlay(polygon);
mask.enableEdgeMove();
mask.addEventListener('mousemove', moveAction);
baidu.on(document, 'mouseup', endAction);
}
/**
* 绘制矩形过程中,鼠标移动过程的事件
*/
var moveAction = function(e) {
polygon.setPath(me._getRectanglePoint(startPoint, e.point));
}
/**
* 绘制矩形结束
*/
var endAction = function (e) {
var calculate = me._calculate(polygon, polygon.getPath()[2]);
me._dispatchOverlayComplete(polygon, calculate);
startPoint = null;
mask.disableEdgeMove();
mask.removeEventListener('mousemove', moveAction);
baidu.un(document, 'mouseup', endAction);
}
mask.addEventListener('mousedown', startAction);
}
/**
* 添加显示所绘制图形的面积或者长度
* @param {overlay} 覆盖物
* @param {point} 显示的位置
*/
DrawingManager.prototype._calculate = function (overlay, point) {
var result = {
data : 0, //计算出来的长度或面积
label : null //显示长度或面积的label对象
};
if (this._enableCalculate && BMapLib.GeoUtils) {
var type = overlay.toString();
//不同覆盖物调用不同的计算方法
switch (type) {
case "[object Polyline]":
result.data = BMapLib.GeoUtils.getPolylineDistance(overlay);
break;
case "[object Polygon]":
result.data = BMapLib.GeoUtils.getPolygonArea(overlay);
break;
case "[object Circle]":
var radius = overlay.getRadius();
result.data = Math.PI * radius * radius;
break;
}
//一场情况处理
if (!result.data || result.data < 0) {
result.data = 0;
} else {
//保留2位小数位
result.data = result.data.toFixed(2);
}
result.label = this._addLabel(point, result.data);
}
return result;
}
/**
* 开启测距和测面功能需要依赖于GeoUtils库
* 所以这里判断用户是否已经加载,若未加载则用js动态加载
*/
DrawingManager.prototype._addGeoUtilsLibrary = function () {
if (!BMapLib.GeoUtils) {
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.setAttribute("src", 'http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js');
document.body.appendChild(script);
}
}
/**
* 向地图中添加文本标注
* @param {Point}
* @param {String} 所以显示的内容
*/
DrawingManager.prototype._addLabel = function (point, content) {
var label = new BMap.Label(content, {
position: point
});
this._map.addOverlay(label);
return label;
}
/**
* 根据起终点获取矩形的四个顶点
* @param {Point} 起点
* @param {Point} 终点
*/
DrawingManager.prototype._getRectanglePoint = function (startPoint, endPoint) {
return [
new BMap.Point(startPoint.lng,startPoint.lat),
new BMap.Point(endPoint.lng,startPoint.lat),
new BMap.Point(endPoint.lng,endPoint.lat),
new BMap.Point(startPoint.lng,endPoint.lat)
];
}
/**
* 派发事件
*/
DrawingManager.prototype._dispatchOverlayComplete = function (overlay, calculate) {
var options = {
'overlay' : overlay,
'drawingMode' : this._drawingType,
'calculate' : calculate.data || null,
'label' : calculate.label || null
};
this.dispatchEvent(this._drawingType + 'complete', overlay);
this.dispatchEvent('overlaycomplete', options);
}
/**
* 创建遮罩对象
*/
function Mask(){
/**
* 鼠标到地图边缘的时候是否自动平移地图
*/
this._enableEdgeMove = false;
}
Mask.prototype = new BMap.Overlay();
/**
* 这里不使用api中的自定义事件,是为了更灵活使用
*/
Mask.prototype.dispatchEvent = baidu.lang.Class.prototype.dispatchEvent;
Mask.prototype.addEventListener = baidu.lang.Class.prototype.addEventListener;
Mask.prototype.removeEventListener = baidu.lang.Class.prototype.removeEventListener;
Mask.prototype.initialize = function(map){
var me = this;
this._map = map;
var div = this.container = document.createElement("div");
var size = this._map.getSize();
div.style.cssText = "position:absolute;background:url(about:blank);cursor:crosshair;width:" + size.width + "px;height:" + size.height + "px";
this._map.addEventListener('resize', function(e) {
me._adjustSize(e.size);
});
this._map.getPanes().floatPane.appendChild(div);
this._bind();
return div;
};
Mask.prototype.draw = function() {
var map = this._map,
point = map.pixelToPoint(new BMap.Pixel(0, 0)),
pixel = map.pointToOverlayPixel(point);
this.container.style.left = pixel.x + "px";
this.container.style.top = pixel.y + "px";
};
/**
* 开启鼠标到地图边缘,自动平移地图
*/
Mask.prototype.enableEdgeMove = function() {
this._enableEdgeMove = true;
}
/**
* 关闭鼠标到地图边缘,自动平移地图
*/
Mask.prototype.disableEdgeMove = function() {
clearInterval(this._edgeMoveTimer);
this._enableEdgeMove = false;
}
/**
* 绑定事件,派发自定义事件
*/
Mask.prototype._bind = function() {
var me = this,
map = this._map,
container = this.container,
lastMousedownXY = null,
lastClickXY = null;
/**
* 根据event对象获取鼠标的xy坐标对象
* @param {Event}
* @return {Object} {x:e.x, y:e.y}
*/
var getXYbyEvent = function(e){
return {
x : e.clientX,
y : e.clientY
}
};
var domEvent = function(e) {
var type = e.type;
e = baidu.getEvent(e);
point = me.getDrawPoint(e); //当前鼠标所在点的地理坐标
var dispatchEvent = function(type) {
e.point = point;
me.dispatchEvent(e);
}
if (type == "mousedown") {
lastMousedownXY = getXYbyEvent(e);
}
var nowXY = getXYbyEvent(e);
//click经过一些特殊处理派发,其他同事件按正常的dom事件派发
if (type == "click") {
//鼠标点击过程不进行移动才派发click和dblclick
if (Math.abs(nowXY.x - lastMousedownXY.x) < 5 && Math.abs(nowXY.y - lastMousedownXY.y) < 5 ) {
if (!lastClickXY || !(Math.abs(nowXY.x - lastClickXY.x) < 5 && Math.abs(nowXY.y - lastClickXY.y) < 5)) {
dispatchEvent('click');
lastClickXY = getXYbyEvent(e);
} else {
lastClickXY = null;
}
}
} else {
dispatchEvent(type);
}
}
/**
* 将事件都遮罩层的事件都绑定到domEvent来处理
*/
var events = ['click', 'mousedown', 'mousemove', 'mouseup', 'dblclick'],
index = events.length;
while (index--) {
baidu.on(container, events[index], domEvent);
}
//鼠标移动过程中,到地图边缘后自动平移地图
baidu.on(container, 'mousemove', function(e) {
if (me._enableEdgeMove) {
me.mousemoveAction(e);
}
});
};
//鼠标移动过程中,到地图边缘后自动平移地图
Mask.prototype.mousemoveAction = function(e) {
function getClientPosition(e) {
var clientX = e.clientX,
clientY = e.clientY;
if (e.changedTouches) {
clientX = e.changedTouches[0].clientX;
clientY = e.changedTouches[0].clientY;
}
return new BMap.Pixel(clientX, clientY);
}
var map = this._map,
me = this,
pixel = map.pointToPixel(this.getDrawPoint(e)),
clientPos = getClientPosition(e),
offsetX = clientPos.x - pixel.x,
offsetY = clientPos.y - pixel.y;
pixel = new BMap.Pixel((clientPos.x - offsetX), (clientPos.y - offsetY));
this._draggingMovePixel = pixel;
var point = map.pixelToPoint(pixel),
eventObj = {
pixel: pixel,
point: point
};
// 拖拽到地图边缘移动地图
this._panByX = this._panByY = 0;
if (pixel.x <= 20 || pixel.x >= map.width - 20
|| pixel.y <= 50 || pixel.y >= map.height - 10) {
if (pixel.x <= 20) {
this._panByX = 8;
} else if (pixel.x >= map.width - 20) {
this._panByX = -8;
}
if (pixel.y <= 50) {
this._panByY = 8;
} else if (pixel.y >= map.height - 10) {
this._panByY = -8;
}
if (!this._edgeMoveTimer) {
this._edgeMoveTimer = setInterval(function(){
map.panBy(me._panByX, me._panByY, {"noAnimation": true});
}, 30);
}
} else {
if (this._edgeMoveTimer) {
clearInterval(this._edgeMoveTimer);
this._edgeMoveTimer = null;
}
}
}
/*
* 调整大小
* @param {Size}
*/
Mask.prototype._adjustSize = function(size) {
this.container.style.width = size.width + 'px';
this.container.style.height = size.height + 'px';
};
/**
* 获取当前绘制点的地理坐标
*
* @param {Event} e e对象
* @return Point对象的位置信息
*/
Mask.prototype.getDrawPoint = function(e) {
var map = this._map,
trigger = baidu.getTarget(e),
x = e.offsetX || e.layerX || 0,
y = e.offsetY || e.layerY || 0;
if (trigger.nodeType != 1) trigger = trigger.parentNode;
while (trigger && trigger != map.getContainer()) {
if (!(trigger.clientWidth == 0 &&
trigger.clientHeight == 0 &&
trigger.offsetParent && trigger.offsetParent.nodeName == 'TD')) {
x += trigger.offsetLeft || 0;
y += trigger.offsetTop || 0;
}
trigger = trigger.offsetParent;
}
var pixel = new BMap.Pixel(x, y);
var point = map.pixelToPoint(pixel);
return point;
}
/**
* 绘制工具面板,自定义控件
*/
function DrawingTool(drawingManager, drawingToolOptions) {
this.drawingManager = drawingManager;
drawingToolOptions = this.drawingToolOptions = drawingToolOptions || {};
// 默认停靠位置和偏移量
this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT;
this.defaultOffset = new BMap.Size(10, 10);
//默认所有工具栏都显示
this.defaultDrawingModes = [
BMAP_DRAWING_MARKER,
BMAP_DRAWING_CIRCLE,
BMAP_DRAWING_POLYLINE,
BMAP_DRAWING_POLYGON,
BMAP_DRAWING_RECTANGLE
];
//工具栏可显示的绘制模式
if (drawingToolOptions.drawingModes) {
this.drawingModes = drawingToolOptions.drawingModes;
} else {
this.drawingModes = this.defaultDrawingModes
}
//用户设置停靠位置和偏移量
if (drawingToolOptions.anchor) {
this.setAnchor(drawingToolOptions.anchor);
}
if (drawingToolOptions.offset) {
this.setOffset(drawingToolOptions.offset);
}
}
// 通过JavaScript的prototype属性继承于BMap.Control
DrawingTool.prototype = new BMap.Control();
// 自定义控件必须实现自己的initialize方法,并且将控件的DOM元素返回
// 在本方法中创建个div元素作为控件的容器,并将其添加到地图容器中
DrawingTool.prototype.initialize = function(map){
// 创建一个DOM元素
var container = this.container = document.createElement("div");
container.className = "BMapLib_Drawing";
//用来设置外层边框阴影
var panel = this.panel = document.createElement("div");
panel.className = "BMapLib_Drawing_panel";
if (this.drawingToolOptions && this.drawingToolOptions.scale) {
this._setScale(this.drawingToolOptions.scale);
}
container.appendChild(panel);
// 添加内容
panel.innerHTML = this._generalHtml();
//绑定事件
this._bind(panel);
// 添加DOM元素到地图中
map.getContainer().appendChild(container);
// 将DOM元素返回
return container;
}
//生成工具栏的html元素
DrawingTool.prototype._generalHtml = function(map){
//鼠标经过工具栏上的提示信息
var tips = {};
tips["hander"] = "拖动地图";
tips[BMAP_DRAWING_MARKER] = "画点";
tips[BMAP_DRAWING_CIRCLE] = "画圆";
tips[BMAP_DRAWING_POLYLINE] = "画折线";
tips[BMAP_DRAWING_POLYGON] = "画多边形";
tips[BMAP_DRAWING_RECTANGLE] = "画矩形";
var getItem = function(className, drawingType) {
var content = '<a class="' + className + '" drawingType="' + drawingType + '" href="javascript:void(0)" title="' + tips[drawingType] + '" οnfοcus="this.blur()"';
if(drawingType == "polygon"){
content += ' οnclick="drawing_onclick(event)"';
}
content += '></a>';
return content;
}
var html = [];
html.push(getItem("BMapLib_box BMapLib_hander", "hander"));
for (var i = 0, len = this.drawingModes.length; i < len; i++) {
var classStr = 'BMapLib_box BMapLib_' + this.drawingModes[i];
if (i == len-1) {
classStr += ' BMapLib_last';
}
if(this.drawingModes[i] == "polygon"){
html.push(getItem(classStr, this.drawingModes[i]));
}
}
return html.join('');
}
/**
* 设置工具栏的缩放比例
*/
DrawingTool.prototype._setScale = function(scale){
var width = 390,
height = 50,
ml = -parseInt((width - width * scale) / 2, 10),
mt = -parseInt((height - height * scale) / 2, 10);
this.container.style.cssText = [
"-moz-transform: scale(" + scale + ");",
"-o-transform: scale(" + scale + ");",
"-webkit-transform: scale(" + scale + ");",
"transform: scale(" + scale + ");",
"margin-left:" + ml + "px;",
"margin-top:" + mt + "px;",
"*margin-left:0px;", //ie6、7
"*margin-top:0px;", //ie6、7
"margin-left:0px\\0;", //ie8
"margin-top:0px\\0;", //ie8
//ie下使用滤镜
"filter: progid:DXImageTransform.Microsoft.Matrix(",
"M11=" + scale + ",",
"M12=0,",
"M21=0,",
"M22=" + scale + ",",
"SizingMethod='auto expand');"
].join('');
}
//绑定工具栏的事件
DrawingTool.prototype._bind = function(panel){
var me = this;
baidu.on(this.panel, 'click', function (e) {
var target = baidu.getTarget(e);
var drawingType = target.getAttribute('drawingType');
me.setStyleByDrawingMode(drawingType);
me._bindEventByDraingMode(drawingType);
});
}
//设置工具栏当前选中的项样式
DrawingTool.prototype.setStyleByDrawingMode = function(drawingType){
if (!drawingType) {
return;
}
var boxs = this.panel.getElementsByTagName("a");
for (var i = 0, len = boxs.length; i < len; i++) {
var box = boxs[i];
if (box.getAttribute('drawingType') == drawingType) {
var classStr = "BMapLib_box BMapLib_" + drawingType + "_hover";
if (i == len - 1) {
classStr += " BMapLib_last";
}
box.className = classStr;
} else {
box.className = box.className.replace(/_hover/, "");
}
}
}
//设置工具栏当前选中的项样式
DrawingTool.prototype._bindEventByDraingMode = function(drawingType){
var drawingManager = this.drawingManager;
//点在拖拽地图的按钮上
if (drawingType == "hander") {
//下行为新增行,根据业务需要修改源代码
drawingManager.setDrawingMode(drawingType);
drawingManager.close();
} else {
drawingManager.setDrawingMode(drawingType);
drawingManager.open();
}
}
//用来存储用户实例化出来的drawingmanager对象
var instances = [];
/*
* 关闭其他实例的绘制模式
* @param {DrawingManager} 当前的实例
*/
function closeInstanceExcept(instance) {
var index = instances.length;
while (index--) {
if (instances[index] != instance) {
instances[index].close();
}
}
}
})();
/**
* 判断两个点相连线段是否与多边形有相交
*
* @param p1 点1
* @param p2 点2
* @param polygon 多边形
*
*/
function isLineCrossPolygon(previousPoint, point, polygon) {
var x1 = previousPoint.lng;
var y1 = previousPoint.lat;
var x2 = point.lng;
var y2 = point.lat;
if (polygon.length < 3) {
return false;
}
for (var index = 0; index < polygon.length; index++) {
var index2 = (index + 1) % polygon.length;
if (isLineCrossLine(x1, y1, x2, y2, polygon[index].lng,
polygon[index].lat, polygon[index2].lng, polygon[index2].lat)) {
return true;
}
}
return false;
}
/**
* 判断线段AB((x1,y1),(x2,y2))和线段CD((x3,y3),(x4,y4))是否相交
*
* @return
*/
function isLineCrossLine(x1, y1, x2, y2, x3, y3, x4, y4) {
// 如果线段的长度为0
if (x1 == x2 && y1 == y2 || x3 == x4 && y3 == y4)
return false;
// 如果两个线段重合
if (x1 == x3 && y1 == y3 || x2 == x3 && y2 == y3 || x1 == x4 && y1 == y4 || x2 == x4 && y2 == y4)
return true;
// 让线段AB的A点与原点(0,0)重合,将两条线段进行整体平移
x2 -= x1;
y2 -= y1;
x3 -= x1;
y3 -= y1;
x4 -= x1;
y4 -= y1;
// 线段AB的长度
var distAB = Math.sqrt(x2 * x2 + y2 * y2);
// 整体旋转两条线段,使线段AB与X轴重合
var theCos = x2 / distAB;
var theSin = y2 / distAB;
var newX = x3 * theCos + y3 * theSin;
y3 = y3 * theCos - x3 * theSin;
x3 = newX;
newX = x4 * theCos + y4 * theSin;
y4 = y4 * theCos - x4 * theSin;
x4 = newX;
// 如果线段CD的Y轴坐标都在X轴的一侧,则不相交
if (y3 < 0 && y4 < 0 || y3 >= 0 && y4 >= 0)
return false;
// 计算直线AB和直线CD的交点
var posAB = x4 + (x3 - x4) * y4 / (y4 - y3);
// 如果交点在X轴的负方向或者交点坐标大于AB长度
if (posAB < 0 || posAB > distAB)
return false;
// 其他情况才相交
return true;
}
/**
* 计算多边形重心点
*
* @param polygon
* @return
*/
function getCenterPointWithPolygon(polygon) {
if (polygon.length < 3)
return;
var p1, p2, p3;
var gx, gy, sumarea;
gx = gy = sumarea = 0.0;
p1 = polygon[0];
p2 = polygon[1];
for (var i = 2; i < polygon.length; i++) {
p3 = polygon[i];
var area = getArea(p1, p2, p3);
gx += (p1.lng + p2.lng + p3.lng) * area;
gy += (p1.lat + p2.lat + p3.lat) * area;
sumarea += area;
p2 = polygon[i];
}
gx = gx / sumarea / 3;
gy = gy / sumarea / 3;
var result = new Object();
result.lng = gx;
result.lat = gy;
return result;
}
/**
* 三角形面积
*/
function getArea(p1, p2, p3) {
return ((p2.lng - p1.lng) * (p3.lat - p1.lat) - (p3.lng - p1.lng) * (p2.lat - p1.lat)) / 2;
}