vehicle routing problem and solution viewer
http://dev.xunhuji.me:17990/snippets/3492ccf925324f208fa9dfe9992e6dba
HTML
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/floatthead/2.0.3/jquery.floatThead.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cache.amap.com/lbs/static/main1119.css">
<script src="https://cache.amap.com/lbs/static/es5.min.js"></script>
<script src="https://webapi.amap.com/maps?v=1.3&key=89c3e1d31cde9b69d4eeff3b94acd6ef&plugin=AMap.Driving,AMap.RangingTool,AMap.ToolBar,AMap.Scale,AMap.MapType"></script>
<script src="https://webapi.amap.com/ui/1.0/main.js"></script>
<div class="container-fluid vrp-workspace">
<div class="vrp-panel-main">
<div id="map-container-gaode" class="vrp-map-container"></div>
<div class="btn-group vrp-panel-input-button">
<button type="button" class="btn btn-sm btn-primary vrp-btn-show-input-modal" data-toggle="modal" data-target="#vrp-modal-input">输入</button>
</div>
<div class="button-group">
<input type="button" class="btn btn-sm btn-info vrp-ranging-distance" value="测距" />
<input type="button" class="btn btn-sm btn-info vrp-set-fit-view" value="显示全部" />
</div>
</div>
<div class="vrp-panel-bottom">
<div class="tabs-left vrp-panel-info-tabs">
<ul class="nav nav-tabs nav-stacked">
<li class="active"><a href="#vrp-tab-summary" data-toggle="tab">Summary</a></li>
<li><a href="#vrp-tab-routes" data-toggle="tab">Routes</a></li>
<li class="hidden vrp-tab-li-detail"><a href="#vrp-tab-detail" data-toggle="tab">Detail</a></li>
</ul>
<div class="tab-content">
<div...
CSS
.vrp-panel-main {
position: absolute;
top: 0;
bottom: 200px;
left: 0;
width: 100%;
}
.vrp-panel-bottom {
background-color: white;
border-top: 1px solid #ddd;
position: absolute;
height: 200px;
bottom: 0;
left: 0;
width: 100%;
overflow-y: hidden;
}
.ui-resizable-handle.ui-resizable-n {
cursor: ns-resize;
}
.vrp-map-container {
height: 100%;
}
.vrp-panel-input-button {
position: absolute;
left: 80px;
top: 20px;
}
#vrp-modal-input {
width: 80%;
max-width: 800px;
}
.vrp-panel-info-tabs {
height: 100%;
}
.tabs-left > .nav-tabs {
border-bottom: 0;
border-right: 1px solid #ddd;
position: absolute;
left: 0;
top: 0;
width: 100px;
height: 100%;
/* overflow-y: scroll; */
padding-top: 3px;
}
.vrp-panel-info-tabs > .tab-content > .tab-pane {
height: 100%;
overflow-y: scroll;
}
.tabs-left > .tab-content {
margin: 10px;
position: absolute;
left: 100px;
top: 0;
right: 0;
height: 100%;
}
.tabs-left > .nav-tabs > li {
float: none;
}
.tabs-left > .nav-tabs > li > a {
min-width: 74px;
margin-right: 0;
margin-bottom: 3px;
}
.tabs-left > .nav-tabs > li > a {
margin-right: -1px;
-webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px;
border-radius: 4px 0 0 4px;
}
.tabs-left > .nav-tabs > li > a:hover,
.tabs-left > .nav-tabs > li > a:focus {
border-color: #eeeeee #dddddd #eeeeee #eeeeee;
}
.tabs-left > .nav-tabs .active > a,
.tabs-left > .nav-tabs .active > a:hover,
.tabs-left > .nav-tabs .active > a:focus {
border-color: #ddd transparent #ddd #ddd;
*border-right-color: #ffffff;
}
.dl-horizontal > dt {
float: left;
width: 160px;
overflow: hidden;
clear: left;
text-align: right;
text-overflow: ellipsis;
white-space: nowrap;
}
.dl-horizontal > dt:after {
padding-left: 5px;
content: ":";
}
.dl-horizontal > dd {
margin-left: 180px;
}
.table-nonfluid {
width: auto;
max-width: 100%;
}
.table-stick-header > thead {
...
JavaScript
var map = new AMap.Map('map-container-gaode', {
resizeEnable: false,
zoom: 10,
});
map.addControl(new AMap.ToolBar());
map.addControl(new AMap.Scale());
map.addControl(new AMap.MapType());
AMapUI.loadUI(['overlay/SvgMarker'], function(SvgMarker) {
AMap.SvgMarker = SvgMarker;
});
var ruler = new AMap.RangingTool(map);
var driving = new AMap.Driving({
map: map,
// panel: 'panel-route',
hideMarkers: true,
showTraffic: true,
});
function loopGet(items, index) {
index %= items.length;
return items[index];
}
function formatTime(time) {
if (time === null) {
return '';
} else if (time === undefined) {
return '-';
}
time = (time * 60).toFixed(0);
var second = time % 60;
time = (time - second) / 60;
var minute = time % 60;
time = (time - minute) / 60;
var hour = time;
hour = ((hour < 10) ? '0' : '') + hour;
minute = ((minute < 10) ? '0' : '') + minute;
second = ((second < 10) ? '0' : '') + second;
return hour + ':' + minute + ':' + second;
}
function formatDistance(distance) {
if (distance === null) {
return '';
} else if (distance === undefined) {
return '-';
}
return distance.toFixed(2);
}
function formatCost(cost) {
return formatDistance(cost);
}
function calcDistance(lon1, lat1, lon2, lat2) {
var r = 6372.8;
var deltaLat = (lat2 - lat1) / 180.0 * Math.PI;
var deltaLon = (lon2 - lon1) / 180.0 * Math.PI;
lat1 = lat1 / 180.0 * Math.PI;
lat2 = lat2 / 180.0 * Math.PI;
var a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.asin(Math.sqrt(a));
var distance = r * c;
return distance;
}
var VehicleRoutingDrawer = (function() {
function VehicleRoutingDrawer(problem, solution) {
var _this = this;
this.warehouseColor = 'red';
this.orderColor = 'blue';
this.unassignedColor = 'red';
this.routeColors = [
'#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c',
...