Javascript 如何根据视图边界动态地将标记从Django服务到google maps? 我有一个Django数据库模型,如下所示: 我的问题是:
我正在尝试在我的前端制作一个Ajaxy google地图,它会发出一个请求,发送视图的左下角和右上角坐标。然后服务器将视图分割成10*10的网格,并从网格中的每个单元向我提供最近的100个点 请求: 服务器看到的内容: getBounds返回一个对象{'pa':{lat:somelat,long:somelong},'xa'{lat:somelat,long:somelong} 例如,在python方面: 我的预编码思想: Django服务器在此视图中接收POSTdata并对其进行处理。理论上,sendNeeded中的算法应该返回视图中的所有点,因为我还没有限制查询 我的数据库有30000多个间隔很好的坐标,这100%不是问题所在。我认为问题在于我的算法,或者我误解了gmaps API通过getBounds返回的结果 重要: 我注意到,当我把视角放大到美国或其他特定的地方时,我偶尔会得到大约10000点的反馈,但这并不一致,我知道这是不对的 服务器视图: csrf豁免测试 我的所有地图代码都用于良好测量:Javascript 如何根据视图边界动态地将标记从Django服务到google maps? 我有一个Django数据库模型,如下所示: 我的问题是:,javascript,python,django,google-maps,coordinates,Javascript,Python,Django,Google Maps,Coordinates,我正在尝试在我的前端制作一个Ajaxy google地图,它会发出一个请求,发送视图的左下角和右上角坐标。然后服务器将视图分割成10*10的网格,并从网格中的每个单元向我提供最近的100个点 请求: 服务器看到的内容: getBounds返回一个对象{'pa':{lat:somelat,long:somelong},'xa'{lat:somelat,long:somelong} 例如,在python方面: 我的预编码思想: Django服务器在此视图中接收POSTdata并对其进行处理。理论上,
我想确认geocodezip写了什么。在玩弄API时,我注意到对于绑定角pa,纬度是'j',经度是'k'。但是对于绑定角xa,纬度是'k',经度是'j'。我无法告诉您这些映射是否一致,所以使用API会更好
如果这样做没有帮助,如果您仍然陷入困境,那么我将非常感谢您提供更多关于您的代码到底要做什么的详细信息-在您发布的代码中,我将花一些时间来找出我应该关注的代码。这不是您当前的问题,但您不希望编写依赖于内部API属性的代码ies例如:['xa']['k'],它们会随着API的每次发布而改变,最终会改变并破坏您的页面
class Point(models.Model):
date = models.DateTimeField(auto_now_add=True)
long = models.DecimalField(max_digits=10, decimal_places=7)
lat = models.DecimalField(max_digits=10, decimal_places=7)
def as_json(self):
return dict(lat=str(self.lat),lng=str(self.long))
def __unicode__(self):
return "date: %s \nlong: %s \nlat: %s\n" % (str(self.date), str(self.lat), str(self.long))
var tosend = {
coords: m_map.getBounds(),
zoom: m_map.getZoom()
};
// alert(JSON.stringify(tosend));
$.ajax({
type: "POST",
url: "/points/",
async: "true",
dataType: "json",
data: JSON.stringify(tosend),
success: updatePins
});
{u'coords': {u'pa': {u'k': -173.3125, u'j': -122.6875}, u'xa': {u'k': -42.51152335203773, u'j': 74.60508620624063}}, u'zoom': 2}
from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext, loader
import json
from models import Point
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def points(request):
return json_flights(request)
def globe(request):
template = loader.get_template('points/globe.html')
context = RequestContext(request)
return HttpResponse(template.render(context))
def json_flights(request):
input = json.loads(request.body)
lb_lat = input['coords']['xa']['k'],
lb_long = input['coords']['pa']['j'],
rt_lat = input['coords']['pa']['k'],
rt_long = input['coords']['xa']['j'],
zoom = input['zoom']
case = 0
#create map_view object for easy passability
map_view = {
'lb_lat' : input['coords']['xa']['k'],
'lb_long' : input['coords']['pa']['j'],
'rt_lat' : input['coords']['pa']['k'],
'rt_long' : input['coords']['xa']['j'],
'zoom' : input['zoom'],
'case' : 0
}
# assign the case to it
if (lb_long < rt_long) and (lb_lat < rt_lat):
map_view['case'] = 0
elif (lb_long < rt_long) and (lb_lat > rt_lat):
map_view['case'] = 1
elif (lb_long > rt_long) and (lb_lat < rt_lat):
map_view['case'] = 2
elif (lb_long > rt_long) and (lb_lat > rt_lat):
map_view['case'] = 3
print "input from client: ", input
pointstosend = []
pointlist = []
#run function to send 100 per square
pointlist = sendOnlyNeeded(map_view)
#get ready to send
json_results = {
'insertdatapayloadhere': "Sample Value",
'coords': pointlist
}
# print "json to send::: ", jsontosend
return HttpResponse(json.dumps(json_results), content_type='application/json')
def sendOnlyNeeded(map_view):
zoom = map_view['zoom']
points_to_return = []
if map_view['case'] == 0:
view_width = map_view['rt_long'] - map_view['lb_long']
view_height = map_view['rt_lat'] - map_view['lb_lat']
elif map_view['case'] == 1:
view_width = map_view['rt_long'] - map_view['lb_long']
view_height = (90 - map_view['lb_lat']) + (map_view['rt_lat'] + 90)
elif map_view['case'] == 2:
view_width = (map_view['rt_long'] + 180) + (180 - map_view['lb_long'])
view_height = map_view['rt_lat'] - map_view['lb_lat']
elif map_view['case'] == 3:
view_width = map_view['rt_long'] - map_view['lb_long']
view_height = map_view['rt_lat'] - map_view['lb_lat']
print 'view_width', view_width , 'view_height', view_height
# constant for tweaking
number_per_unit = 100
# set the grid dimensions
griddimensions = [10, 10]
#find the height and width of each rectangle within the view
unit_height = view_height / griddimensions[1]
unit_width = view_width / griddimensions[0]
#iterate by viewable gridunit and filter the num_per_gu markers to send.
# starting at lb_lat, chop up and push markers from grid until you get to rt_lat
# start>------->
# >------------>
# >--------->end
long_cursor = map_view['lb_long']
lat_cursor = map_view['lb_lat']
widthcount = 0;
heightcount = 0
print "view height::::::", view_height
while heightcount < view_height:
if lat_cursor > 90:
lat_cursor = -90
while widthcount < view_width:
unitbounds = {
'lb_lat': lat_cursor,
'rt_lat': lat_cursor + unit_height,
'lb_long': long_cursor ,
'rt_long': long_cursor + unit_width
}
print "unitbounds: ", unitbounds
querySetResult = getMarkersinBox(unitbounds, number_per_unit)
for cords in querySetResult:
points_to_return.append([float(cords.long), float(cords.lat)])
#points_to_return.append(preparedata(getMarkersinBox(unitbounds, number_per_unit)))
#check if you went off the map. notice we let it overflow. this way, we're guaranteed not to miss any points.
long_cursor += unit_width
if long_cursor > 180:
long_cursor = -180
#counter to stop
widthcount += unit_width
print "widthcount::::", widthcount
lat_cursor += unit_height
heightcount += unit_height
print "heightcount:::", heightcount
return points_to_return
def getMarkersinBox(unitbounds, number_per_unit):
from django.db.models import Q
numbtosend = number_per_unit
lb_lat = unitbounds['lb_lat']
lb_long = unitbounds['lb_long']
rt_lat = unitbounds['rt_lat']
rt_long = unitbounds['rt_long']
if (lb_long < rt_long) and (lb_lat < rt_lat):
queryresult = Point.objects.filter(long__gte=lb_long, long__lte=rt_long, lat__gte=lb_lat, lat__lte=rt_lat).order_by('id')
elif (lb_long < rt_long) and (lb_lat > rt_lat):
queryresult = Point.objects.filter(Q(long__gte=lb_long), Q(long__lte=rt_long), Q(lat__gte=lb_lat) | Q(lat__lte=rt_lat)).order_by('id')
elif (lb_long > rt_long) and (lb_lat < rt_lat):
queryresult = Point.objects.filter(Q(long__gte=lb_long) | Q(long__lte=rt_long), Q(lat__gte=lb_lat), Q(lat__lte=rt_lat)).order_by('id')
elif (lb_long > rt_long) and (lb_lat > rt_lat):
queryresult = Point.objects.filter(Q(long__gte=lb_long) | Q(long__lte=rt_long), Q(lat__gte=lb_lat) | Q(lat__lte=rt_lat)).order_by('id')
return queryresult
var m_infoBox = null;
var m_map;
var markers = [];
var image = {
url: '/static/pictures/map_globe_pin.png',
size: new google.maps.Size(18, 17),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(8, 8)
};
var sampd;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(32.000000, 32.000000),
zoom: 2,
minZoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
m_map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
google.maps.event.addListener(m_map, 'idle', queryServerForMarkers);
google.maps.event.addListenerOnce(m_map, 'idle', function() {
fixPanHandles();
});
google.maps.event.addListenerOnce(m_map, 'idle', function() {
setTimeout(function() {
fixPanHandles();
}, 500);
});
google.maps.event.addListener(m_map, 'bounds_changed', function() {
checkIfMarkersStillVisible();
});
m_map.getMinimumResolution = function() {
return 12;
};
}
google.maps.event.addDomListener(window, 'load', initialize);
function checkIfMarkersStillVisible() {
for (var i = 0; i < markers.length; i++) {
if (!m_map.getBounds().contains(markers[i].getPosition())) {
markers[i].setMap(null);
} else {
markers[i].setMap(m_map);
}
}
}
function InfoBox(opts, uid, mid, content) {
google.maps.OverlayView.call(this);
this.latlng_ = opts.latlng;
this.map_ = opts.map;
this.offsetVertical_ = -76;
this.offsetHorizontal_ = -105;
this.height_ = 58;
this.uid_ = uid;
this.mid_ = mid;
this.content_ = content;
var me = this;
this.boundsChangedListener_ =
google.maps.event.addListener(this.map_, "bounds_changed", function() {});
this.setMap(this.map_);
return this;
}
function queryServerForMarkers() {
//clean up first
var tosend = {
coords: m_map.getBounds(),
zoom: m_map.getZoom()
};
// alert(JSON.stringify(tosend));
$.ajax({
type: "POST",
url: "/points/",
async: "true",
dataType: "json",
data: JSON.stringify(tosend),
success: updatePins
});
}
function updatePins(data) {
sampd = data;
//tells you center:
console.table("Bounds of view: " + m_map.getBounds() + "\ngot new pins: " + data.coords.length + JSON.stringify(data.coords));
for (var i = 0; i < data.length; i++) {
if ($.inArray(data[i], markers) != -1) {
continue;
}
var coords = new google.maps.LatLng(data.coords[i][0], data.coords[i][1]);
setMarker(m_map, coords, 0, 1223, 1122);
//debug for coords
console.log({
'lat': parseFloat(data.coords[i][0]),
'lng': parseFloat(data.coords[i][1])
});
}
}
function setMarker(map, markerLatLng, markerzIndex, uid, mid) {
var marker = new google.maps.Marker({
position: markerLatLng,
map: map,
icon: image,
// animation: google.maps.Animation.DROP,
zIndex: markerzIndex
});
google.maps.event.addListener(marker, 'mouseover', function() {
if (m_infoBox) {
if (m_infoBox.mid_ == mid) {
return;
}
m_infoBox.setMap(null);
m_infoBox = null;
}
content = loadContent(uid);
m_infoBox = new InfoBox({
latlng: marker.getPosition(),
map: m_map
}, uid, mid, content);
});
markers.push(marker);
}
function loadContent(uid) {
var response = '';
$.ajax({
type: "GET",
url: "/service/globe_float_content/?uid=" + uid,
async: true,
success: function(text) {
response = text;
}
});
return response;
}
InfoBox.prototype = new google.maps.OverlayView();
InfoBox.prototype.remove = function() {
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
InfoBox.prototype.draw = function() {
// Creates the element if it doesn't exist already.
this.createElement();
if (!this.div_) return;
// Calculate the DIV coordinates of two opposite corners of our bounds to
// get the size and position of our Bar
var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
if (!pixPosition) return;
this.div_.style.display = 'block';
// Assign the correct width for the popup pane to fully display all details in the popup
var divWidth = $('#float_avatar').width() + $('#float_name').width() + 32;
$('#float_tip_down').css("left", ((divWidth / 2) - 20) + "px");
this.div_.style.width = divWidth + "px";
this.div_.style.left = (pixPosition.x - (divWidth / 2)) + "px";
this.div_.style.height = this.height_ + "px";
this.div_.style.top = (pixPosition.y + this.offsetVertical_) + "px";
};
function fixPanHandles() {
//fix bug with IE and gmaps pan hotspots.
$('#map-canvas div[title^="Pan"]').css("opacity", 0);
}
function setAllMap(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}