L.TileLayer.GoogleBase = L.TileLayer.extend({ getTileUrl: function (coords) { return '/Beijing/GetMap?type=47626774&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y); } }); L.TileLayer.GoogleDetail = L.TileLayer.extend({ getTileUrl: function (coords) { return '/Beijing/GetMap?type=1024577166&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y); } }); L.TileLayer.GaodeBase = L.TileLayer.extend({ getTileUrl: function (coords) { return '/Beijing/GetMap?type=1542757547&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y); } }); L.TileLayer.GaodeDetail = L.TileLayer.extend({ getTileUrl: function (coords) { return '/Beijing/GetMap?type=1447870524&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y); } }); L.TileLayer.GaodeOther = L.TileLayer.extend({ getTileUrl: function (coords) { return '/Beijing/GetMap?type=788865972&zoom={0}&x={1}&y={2}'.format(coords.z, coords.x, coords.y); } }); L.tileLayer.googleBase = function () { return new L.TileLayer.GoogleBase(); }; L.tileLayer.googleDetail = function () { return new L.TileLayer.GoogleDetail(); }; L.tileLayer.gaodeBase = function () { return new L.TileLayer.GaodeBase(); }; L.tileLayer.gaodeDetail = function () { return new L.TileLayer.GaodeDetail(); }; L.tileLayer.gaodeOther = function () { return new L.TileLayer.GaodeOther(); }; var Map = function (parent) { this.Parent = parent; this.WindTemplate = null; this.MultiLayers = false; this.CompareLayers = false; this.layers = false; this.isMark = false; this.ForecastPoints = null; this.ForecastBackwardPoints = null; this.ForecastForwardPoints = null; this.RealTimeData = null; this.RealTimeBackwardPoints = null; this.RealTimeForwardPoints = null; this.forwardStopPoint = null; this.centerPointTime = null; this.InfoPoint = new InfoPoint(this); this.Startup = function () { this.CreateMap(); this.InitCapture(); this.LoadWindTemplate(); this.LoadInfoPoint(); this.InfoPoint.Startup(); $('#mark-button').on('click', this.onMarkClick.bind(this)); $('#draw-button').on('click', this.OnDrawButtonClick.bind(this)); $('#clear-button').on('click', this.OnClearButtonClick.bind(this)); $('#particle-switch a').on('click', this.OnParticleButtonClick.bind(this)); $('#label-switch a').on('click', this.OnRemoveMarkersButtonClick.bind(this)); }; this.CreateMap = function () { this.map = L.map('map', { zoomControl: false, minZoom: 4, maxZoom: 16, zoomDelta: 0.05 }).setView([39.90, 116.40], 11); L.tileLayer.googleBase().addTo(this.map); L.tileLayer.googleDetail().addTo(this.map); L.tileLayer.gaodeBase().addTo(this.map); L.tileLayer.gaodeDetail().addTo(this.map); L.tileLayer.gaodeOther().addTo(this.map); $('.leaflet-control-attribution').hide(); this.map.on('mousemove', this.OnMapMove.bind(this)) }; this.CenterMap = function (lat, lng) { this.map.setView([lat, lng], 11); }; this.OnMapMove = function (e) { $('.latlng').text('当前经纬度:{0}, {1}'.format(this.getLatLng(e.latlng.lng), this.getLatLng(e.latlng.lat))) }; this.getLatLng = function (value) { value = value.toString() let index = value.indexOf('.') if (index !== -1) { value = value.substring(0, 6 + index + 1) } else { value = value.substring(0) } return parseFloat(value).toFixed(6) } this.OnParticleButtonClick = function () { // Toggle switch on/off var parent = $(event.target).parent(); parent.toggleClass('switch-on'); // Hide wind layer if (!parent.hasClass('switch-on')) { this.HideWindLayer(); return; } // Add wind layer var url = 'http://{0}/bj/getwind/{1}'.format(Config.ApiRoot, this.GetWindFileName()); $.getJSON(url).done(function (data) { this.WindTemplate[0].data = []; this.WindTemplate[1].data = []; $(data).each(function (index, item) { this.WindTemplate[0].data.push(item.u); this.WindTemplate[1].data.push(item.v); }.bind(this)); this.ShowWindLayer(this.WindTemplate); }.bind(this)).fail(function (xhr, status, error) { var message = "Json文件加载失败: Status={0}, Error={1}".format(status, error); this.MessageBox("error", message); }.bind(this)); }; this.OnRemoveMarkersButtonClick = function () { var parent = $(event.target).parent(); parent.toggleClass('switch-on'); if (!parent.hasClass('switch-on')) { $('.point').hide(); $('.time-label').hide(); } else { $('.point').show(); $('.time-label').show(); } }; this.OnDrawButtonClick = function () { if (this.map.hasLayer(this.lineLayer)) this.map.removeLayer(this.lineLayer); this.point = []; this.lineLayer = new L.FeatureGroup(); this.map.addLayer(this.lineLayer); this.map.on(L.Draw.Event.CREATED, function (e) { this.lineLayer.addLayer(e.layer); this.point.push([e.layer._latlngs[0].lng, e.layer._latlngs[0].lat], [e.layer._latlngs[1].lng, e.layer._latlngs[1].lat]); this.AddPoints(this.lineLayer, this.point, 2, '#000000', '#ffffff'); this.SetDistance(e.layer._latlngs[0].lng, e.layer._latlngs[0].lat, e.layer._latlngs[1].lng, e.layer._latlngs[1].lat, this.lineLayer); }.bind(this)); this.map.on(L.Draw.Event.DRAWVERTEX, function (e) { var layerIds = Object.keys(e.layers._layers); if (layerIds.length > 1) { var secondVertex = e.layers._layers[layerIds[1]]._icon; requestAnimationFrame(() => secondVertex.click()); } }.bind(this)); var drawer = new L.Draw.Polyline(this.map, {}); drawer.enable(); }; this.OnClearButtonClick = function () { if (this.map.hasLayer(this.lineLayer)) this.map.removeLayer(this.lineLayer); }; this.GetWindFileName = function () { var value = $('#release-date').datebox('getValue'); var time = moment(value, 'YYYY/MM/DD HH:mm'); var hour = time.format('YYYY-MM-DD_HH'); var minute = Math.floor(time.minutes() / 10) * 10; return '{0}_{1}.json'.format(hour, minute === 0 ? '00' : minute); }; this.LoadWindTemplate = function () { $.getJSON('/Content/scripts/beijing/wind-template.json', function (data) { this.WindTemplate = data; }.bind(this)); }; this.RemoveLayer = function (name) { this.map.eachLayer(function (layer) { if (layer.name === name) this.map.removeLayer(layer); }.bind(this)); }; this.ClearLayers = function () { this.map.eachLayer(function (layer) { if (layer.name !== undefined) this.map.removeLayer(layer); }.bind(this)); }; this.LoadAverageData = function (name, param, result) { this.centerPointTime = param.ReleaseTime; this.ClearLiveLayer(name); var layer = this.CreateAverageLayer(name, param, result); this.map.addLayer(layer); this.BindCloseButtons(); }; this.ClearLiveLayer = function (name) { if (this.MultiLayers) this.RemoveLayer(name); else this.ClearLayers(); if (this.map.hasLayer(this.groundLayer)) this.map.removeLayer(this.groundLayer); if (this.map.hasLayer(this.notGroundLayer)) this.map.removeLayer(this.notGroundLayer); }; this.LoadRealTimeData = function (name, result) { if (this.MultiLayers) this.RemoveLayer(name); this.CompareLayers = this.CreateCompareLayer(name, result); this.SetRealTimeData(result); this.map.addLayer(this.CompareLayers); this.BindCloseButtons(); var isPullDown = $("#control-switch").hasClass("control-switch-on"); this.Parent.Map.IsPullGround(isPullDown); }; this.IsPullGround = function (isGround) { if (this.map.hasLayer(this.groundLayer)) this.map.removeLayer(this.groundLayer); if (this.map.hasLayer(this.notGroundLayer)) this.map.removeLayer(this.notGroundLayer); this.groundLayer = new L.FeatureGroup(); this.notGroundLayer = new L.FeatureGroup(); if (isGround) { this.map.removeLayer(this.notGroundLayer); this.map.addLayer(this.groundLayer); this.GroundDistancePolyline(this.groundLayer); } else { this.map.addLayer(this.groundLayer); this.map.addLayer(this.notGroundLayer); this.DistancePolyline(this.notGroundLayer); } }; this.BindCloseButtons = function () { $('.close-button').on('click', function (event) { $('.{0}'.format($(event.target).next().attr('lng'))).hide(); $(event.target).parent().hide(); }); }; this.LoadDetailData = function (name, values) { this.ClearLayers(); var layer = this.CreateDetailLayer(name, values); this.map.addLayer(layer); }; this.CreateDetailLayer = function (name, values) { var features = new L.FeatureGroup(); features.name = name; this.AddData(features, values); return features; }; this.CreateAverageLayer = function (name, param, result) { var features = new L.FeatureGroup(); features.name = name; this.AddData(features, result.backward.average); this.AddData(features, result.forward.average); this.AddPolyline(features, result.backward.points, '#ffffff', '#cccccc'); this.AddPolyline(features, result.forward.points, '#ffffff', '#cccccc'); this.AddCenter(features, param); this.AddPoints(features, result.backward.points, 0.5, '#000000', '#ffffff'); this.AddPoints(features, result.forward.points, 0.5, '#000000', '#ffffff'); this.AddLabels(features, result.backward.points, 'actual'); this.AddLabels(features, result.forward.points, 'actual'); return features; }; this.CreateCompareLayer = function (name, result) { var features = new L.FeatureGroup(); features.name = name; this.AddPolyline(features, result, 'blue', '#000000'); this.AddPoints(features, result, 1, 'blue', '#ffffff'); this.AddLabels(features, result, 'compare'); return features; }; this.AddData = function (features, values) { $(values).each(function (index, value) { var color = this.GetPointsColor(value[2]); var bounds = [[value[1] - 0.005, value[0] - 0.005], [value[1] + 0.005, value[0] + 0.005]]; L.rectangle(bounds, { color: color, fillColor: color, fillOpacity: 0.75, weight: 0 }).addTo(features); }.bind(this)); }; this.AddPolyline = function (features, points, color, fillColor) { var polyline = []; $(points).each(function (index, point) { polyline.push([point[1], point[0]]); }); L.polyline(polyline, { fillColor: fillColor, color: color, weight: 2 }).addTo(features); }; this.SetForecastData = function (data) { this.ForecastPoints = data; this.ForecastBackwardPoints = data.backward.points; this.ForecastForwardPoints = data.forward.points; }; this.SetRealTimeData = function (data) { this.RealTimeData = data; var index = this.GetRealTimeCenterIndex(data); var backwardPoints = data.slice(0, index); var forwardPoints = data.slice(index + 1, data.length + 1); this.RealTimeBackwardPoints = this.GetSamePoints(backwardPoints, this.ForecastBackwardPoints).realtime; this.RealTimeForwardPoints = this.GetSamePoints(forwardPoints, this.ForecastForwardPoints).realtime; this.ForecastBackwardPoints = this.GetSamePoints(backwardPoints, this.ForecastBackwardPoints).forecast; this.ForecastForwardPoints = this.GetSamePoints(forwardPoints, this.ForecastForwardPoints).forecast; }; this.GetSamePoints = function (forecastData, realtimeData ) { var realtime = []; var forecast = []; for (var i = 0; i < forecastData.length; i++) { for (var j = 0; j < realtimeData.length; j++) { if (realtimeData[j][3] === forecastData[i][3]) { realtime.push(realtimeData[j]); forecast.push(forecastData[i]); } } } return { realtime: realtime, forecast: forecast }; }; this.GetRealTimeCenterIndex = function (data) { var flag = 0; for (var i = 0; i < data.length; i++) { var time = moment(data[i][3], "YYYYMMDD_HHmmss"); if (time.format("YYYY/MM/DD HH:mm") === this.centerPointTime) flag = i; } return flag; }; this.DistancePolyline = function (features) { this.AddMaxDistancePolyline(this.GetBackwardPoints().forecastLon, this.GetBackwardPoints().forecastLat, this.GetBackwardPoints().realtimeLon, this.GetBackwardPoints().realtimeLat, features); this.AddMaxDistancePolyline(this.GetforwardPoints().forecastLon, this.GetforwardPoints().forecastLat, this.GetforwardPoints().realtimeLon, this.GetforwardPoints().realtimeLat, features); }; this.GroundDistancePolyline = function (features) { let from = { longitude: this.ForecastPoints.backward.points[0][0], latitude: this.ForecastPoints.backward.points[0][1] }; let to = { longitude: this.RealTimeData[0][0], latitude: this.RealTimeData[0][1] }; this.AddStartStopPolyline(from.longitude, from.latitude, to.longitude, to.latitude, features); }; this.AddMaxDistancePolyline = function (forecastLon, forecastLat, realtimeLon, realtimeLat, features) { this.AddStartStopPolyline(forecastLon, forecastLat, realtimeLon, realtimeLat, features); }; this.GetBackwardPoints = function (features) { var backwardPoints = []; var maxItem = []; $(this.ForecastBackwardPoints).each(function (index, point) { var forecastPoint = this.GetPoints(point); var realtimePoint = this.GetPoints(this.RealTimeBackwardPoints[index]); var distance = this.CalcDistance(forecastPoint, realtimePoint); maxItem.push(distance); backwardPoints.push(distance); }.bind(this)); var backwardIndex = this.GetMaxIndex(backwardPoints, maxItem.sort(function (a, b) { return a - b; }).reverse()[0]); return { forecastLon: this.ForecastBackwardPoints[backwardIndex][0], forecastLat: this.ForecastBackwardPoints[backwardIndex][1], realtimeLon: this.RealTimeBackwardPoints[backwardIndex][0], realtimeLat: this.RealTimeBackwardPoints[backwardIndex][1] }; }; this.GetforwardPoints = function (features) { var forwardPoints = []; var maxItem = []; $(this.ForecastForwardPoints).each(function (index, point) { var forecastPoint = this.GetPoints(point); var realtimePoint = this.GetPoints(this.RealTimeForwardPoints[index]); var distance = this.CalcDistance(forecastPoint, realtimePoint); maxItem.push(distance); forwardPoints.push(distance); }.bind(this)); var forwardIndex = this.GetMaxIndex(forwardPoints, maxItem.sort(function (a, b) { return a - b; }).reverse()[0]); return { forecastLon: this.ForecastForwardPoints[forwardIndex][0], forecastLat: this.ForecastForwardPoints[forwardIndex][1], realtimeLon: this.RealTimeForwardPoints[forwardIndex][0], realtimeLat: this.RealTimeForwardPoints[forwardIndex][1] }; }; this.GetPoints = function (point) { return { Longitude: point[0], Latitude: point[1], Height: point[2] }; }; this.AddMaxGroundDistancePolyline = function (features) { var forecastLon = this.ForecastForwardPoints[this.ForecastForwardPoints.length - 1][0]; var forecastLat = this.ForecastForwardPoints[this.ForecastForwardPoints.length - 1][1]; var realtimeLon = this.RealTimeBackwardPoints[this.RealTimeBackwardPoints.length - 1][0]; var realtimeLat = this.RealTimeBackwardPoints[this.RealTimeBackwardPoints.length - 1][1]; this.AddStartStopPolyline(forecastLon, forecastLat, realtimeLon, realtimeLat, features); }; this.AddStartStopPolyline = function (forecastLon, forecastLat, realtimeLon, realtimeLat, features) { this.SetDistance(forecastLon, forecastLat, realtimeLon, realtimeLat, features); var polyline = [[forecastLat, forecastLon], [realtimeLat, realtimeLon]]; L.polyline(polyline, { fillColor: 'yellow', color: 'yellow', weight: 2, className: 'dashLines' }).addTo(features); }; this.GetMaxIndex = function (array, value) { var count = ("," + array.toString() + ",").split("," + value + ","); var index = count[0].split(",").length - 1; return index; }; this.CalcDistance = function (forecastPoint, realtimePoint) { var from = L.latLng(forecastPoint.Latitude, forecastPoint.Longitude); var to = L.latLng(realtimePoint.Latitude, realtimePoint.Longitude); let distance = from.distanceTo(to); return distance / 1000; //let height = Math.abs(forecastPoint.Height - realtimePoint.Height); //let meter = Math.sqrt(distance * distance + height * height); //return meter / 1000; }; this.SetDistance = function (fromLon, fromLat, toLon, toLat, features) { var lon = (fromLon + toLon) / 2; var lat = (fromLat + toLat) / 2; var from = L.latLng(fromLat, fromLon); var to = L.latLng(toLat, toLon); var bounds = from.distanceTo(to); L.marker([lat, lon], { icon: L.divIcon({ className: 'distance', html: '两点之间距离为:{0}公里'.format(Math.round((bounds / 1000) * 100) / 100) }) }).addTo(features); }; this.AddCenter = function (features, param) { var latlng = [param.Latitude, param.Longitude]; L.circleMarker(latlng, { opacity: 1, weight: 0.5, color: 'black', fillColor: 'yellow', fillOpacity: 0.5, radius: 6 }).addTo(features); L.marker(latlng, { icon: L.divIcon({ className: 'center-label', html: this.GetCenterLabel(param) }) }).addTo(features); }; this.AddPoints = function (features, points, weight, color, fillColor) { $(points).each(function (index, point) { L.circleMarker([point[1], point[0]], { opacity: 1, weight: weight, color: color, fillColor: fillColor, fillOpacity: 1, radius: 4, className: 'point point{0}'.format(point[1].toString().split(".").join("")) }).addTo(features); }.bind(this)); }; this.AddLabels = function (features, points, className) { $(points).each(function (index, point) { var item = className === 'actual' ? point[3] : point[2]; L.marker([point[1], point[0]], { icon: L.divIcon({ className: 'time-label {0}-time-label'.format(className), html: this.NormalizeTime(point[1], point[3]) }) }).addTo(features); }.bind(this)); }; this.GetCenterLabel = function (param) { var pattern = '
经度:{0}
纬度:{1}
高度:{2}米
释放时间:{3}
'; return pattern.format(param.Longitude, param.Latitude, param.Height, moment(param.ReleaseTime).format("MM/DD HH:mm")); }; this.NormalizeTime = function (lng, time) { var attr = lng.toString().split(".").join(""); var value = moment(time, "YYYYMMDD_HHmmss"); return '{1}'.format(attr, value.format("MM/DD HH:mm")); }; this.ShowWindLayer = function (data) { this.WindLayer = L.velocityLayer({ displayValues: false, displayOptions: { velocityType: 'GBR Wind', displayPosition: 'bottomleft', displayEmptyString: 'No wind data' }, data: data, maxVelocity: 15 }); this.map.addLayer(this.WindLayer); }; this.HideWindLayer = function () { if (this.map.hasLayer(this.WindLayer)) this.map.removeLayer(this.WindLayer); }; this.InitCapture = function () { Init(); $('#capture-button').on('click', function () { var returned = Capture(); if (returned === emCaptureFailed || returned === emCaptureUnknown) { $('#capture-button').hide(); $('#download-button').show(); } }); }; this.GetPointsColor = function (value) { if (value <= 0.0001) return 'rgb(255,255,255)'; if (value <= 0.001) return 'rgb(178, 226, 249)'; if (value <= 0.01) return 'rgb(93, 160, 213)'; if (value <= 0.1) return 'rgb(73, 170, 106)'; if (value <= 1) return 'rgb(159, 206, 81)'; if (value <= 10) return 'rgb(248, 171, 67)'; if (value <= 100) return 'rgb(239, 94, 41)'; if (value <= 1000) return 'rgb(192, 28, 36)'; }; this.LoadInfoPoint = function () { $.ajax({ type: "POST", dataType: 'text', url: '/Point/Query', success: function (result) { var data = JSON.parse(result); data.forEach(function (item, index) { var point = { lat: item.Latitude, lng: item.Longitude }; this.AddInfoPoint(point, item.Title, item.Icon, item.Id) }.bind(this)) }.bind(this) }); }; this.onMarkClick = function () { this.isMark = true; $('#map').css('cursor', 'crosshair'); this.DrewInfoPoint(); }; this.DrewInfoPoint = function () { this.map.on('click', function (e) { if (this.isMark) this.InfoPoint.ShowDialog(e.latlng); else return; }.bind(this)) }; this.AddInfoPoint = function (point, title, icon, id) { let label = '{1}