Created
April 19, 2012 06:04
-
-
Save mapmeld/2419014 to your computer and use it in GitHub Desktop.
Red Pen: experimental auto-marker for FieldPapers.org
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Red Pen turns red (and blue!) dots on Field Papers tiles into markers automatically | |
Tested with Sharpie and PaperMate ballpoint pens | |
Write a description to save the marker | |
I don't understand the server-side installation or the QR-scanning, so I'm using a bookmarklet | |
Client-side HTML5 Canvas for tile inspection | |
*/ | |
// collect the most zoomed-in tiles from the scan | |
var zoomimgs = document.getElementsByTagName("img"); | |
var maxzoom = 0; | |
var maxzoomitems = [ ]; | |
for(var z=0; z<zoomimgs.length; z++){ | |
if(zoomimgs[z].src.split('/').length > 7){ | |
if(zoomimgs[z].src.split('/')[4] == "scans"){ | |
if(zoomimgs[z].src.split('/')[6] > maxzoom){ | |
maxzoom = zoomimgs[z].src.split('/')[6]; | |
maxzoomitems = [ zoomimgs[z] ]; | |
} | |
else if(zoomimgs[z].src.split('/')[6] == maxzoom){ | |
maxzoomitems.push( zoomimgs[z] ); | |
} | |
} | |
} | |
} | |
var tileCanvas = document.createElement("canvas"); | |
tileCanvas.width = 256; | |
tileCanvas.height = 256; | |
// dev: spy on the process | |
tileCanvas.position = "fixed"; | |
tileCanvas.top = 0; | |
tileCanvas.left = 0; | |
document.body.appendChild(tileCanvas); | |
var tileCtx = tileCanvas.getContext("2d"); | |
var reddots = [ ]; | |
var bluedots = [ ]; | |
for(var mz=0;mz<maxzoomitems.length;mz++){ | |
tileCtx.drawImage(maxzoomitems[mz], 0, 0, 256, 256); | |
var imgData = tileCtx.getImageData(0, 0, 256, 256); | |
for(var x=0; x<256; x++){ | |
for(var y=0; y<256; y++){ | |
//console.log(x + "," + y); | |
var r = imgData.data[y*4*256+x*4]; | |
var g = imgData.data[y*4*256+x*4+1]; | |
var b = imgData.data[y*4*256+x*4+2]; | |
var a = imgData.data[y*4*256+x*4+3]; | |
if((r > 160 && g < 80 & b < 80) || (r > 150 && g < 70 & b < 70) || (r > 110 && g < 60 & b < 60) || ( r > 140 && g < 90 && b < 110 )){ | |
//imgData.data[y*4*256+x*4+2] = 250; | |
//console.log("red"); | |
var transform = maxzoomitems[mz].style.webkitTransform.split(","); | |
reddots.push([ (transform[12] * 1 + x) , (transform[13] * 1 + y) ]); | |
//console.log( (transform[12] * 1 + x) + "," + (transform[13] * 1 + y) ); | |
} | |
else if( ( r < 90 && g < 110 & b > 150 ) || (r < 50 && g < 50 && b > 80) ){ | |
// blue dot? | |
var transform = maxzoomitems[mz].style.webkitTransform.split(","); | |
bluedots.push([ (transform[12] * 1 + x) , (transform[13] * 1 + y) ]); | |
} | |
} | |
} | |
} | |
function MarkerNotePlus(map, post_url) | |
{ | |
var marker_width = 30; | |
var marker_height = 30; | |
var note_displayed = true; | |
this.location = map.getCenter(); | |
var data = this.data = { | |
'lat': this.location.lat, | |
'lon': this.location.lon, | |
'marker_number': markerNumber, | |
'user_id': current_user_id, | |
'note': '' | |
}; | |
this.location = map.getCenter(); | |
var div = document.createElement('div'); | |
div.className = 'marker'; | |
var img = document.createElement('img'); | |
img.src = 'img/icon_x_mark_new.png'; | |
div.appendChild(img); | |
var new_marker_text_area = document.getElementById('new_marker_textarea'); | |
var submitNote = function() | |
{ | |
if (new_marker_text_area.value.trim() == ''){ | |
alert('Please fill out your note!'); | |
return false; | |
} else { | |
reqwest({ | |
url: post_url, | |
method: 'post', | |
data: data, | |
type: 'json', | |
error: function(err) { | |
console.log('error', err); | |
}, | |
success: function (resp) { | |
//console.log('resp', resp); | |
changeMarkerDisplay(resp); | |
} | |
}); | |
active_marker = false; | |
note_displayed = false; | |
return false; | |
} | |
} | |
var changeMarkerDisplay = function(resp) | |
{ | |
new_marker_text_area.value = ''; | |
div.parentNode.removeChild(div); | |
var new_marker_note = document.getElementById('new_marker_note'); | |
new_marker_note.className = 'hide'; | |
var note = resp.note_data; | |
if (!note.username) | |
{ | |
note.username = 'Anonymous'; | |
} | |
addSavedNote(note.note,note.username,note.created,note.marker_number,note.latitude,note.longitude); | |
} | |
var removeMarkerNote = function() | |
{ | |
div.parentNode.removeChild(div); | |
var editable_new_note = document.getElementById('new_marker_note'); | |
editable_new_note.className = 'hide'; | |
active_marker = false; | |
note_displayed = false; | |
} | |
var input_lat = document.createElement('input'); | |
input_lat.value = this.location.lat.toFixed(6); | |
input_lat.type = 'hidden'; | |
input_lat.name = 'marker[' + markerNumber + '][lat]'; | |
div.appendChild(input_lat); | |
var input_lon = document.createElement('input'); | |
input_lon.value = this.location.lon.toFixed(6); | |
input_lon.type = 'hidden'; | |
input_lon.name = 'marker[' + markerNumber + '][lon]'; | |
div.appendChild(input_lon); | |
var scan_id = document.createElement('input'); | |
scan_id.value = scan_id; | |
scan_id.name = 'marker[' + markerNumber + '][scan_id]'; | |
scan_id.type = 'hidden'; | |
div.appendChild(scan_id); | |
var user_id = document.createElement('input'); | |
user_id.value = current_user_id; | |
user_id.name = 'marker[' + markerNumber + '][scan_id]'; | |
user_id.type = 'hidden'; | |
div.appendChild(user_id); | |
markerNumber--; | |
// make it easy to drag | |
img.onmousedown = function(e) | |
{ | |
if (active_polygon != -1 || (active_marker && !note_displayed) || draw_mode) | |
{ | |
return; | |
} | |
active_marker = true; | |
note_displayed = true; | |
var ok_button = document.getElementById('new_marker_ok_button'); | |
ok_button.onclick = submitNote; | |
var remove_button = document.getElementById('new_marker_delete_button'); | |
remove_button.onclick = removeMarkerNote; | |
var editable_new_note = document.getElementById('new_marker_note'); | |
editable_new_note.className = 'show'; | |
var editable_new_note_textarea = document.getElementById('new_marker_textarea'); | |
editable_new_note_textarea.onchange = function () { | |
data.note = this.value; | |
}; | |
//var marker_width = 30; | |
var offsetY = 5; | |
editable_new_note.style.position = "absolute"; | |
editable_new_note.style.left = div.offsetLeft - .5*editable_new_note.offsetWidth + .5*marker_width + 'px'; | |
editable_new_note.style.top = div.offsetTop - editable_new_note.offsetHeight - offsetY + 'px'; | |
var marker_start = {x: div.offsetLeft, y: div.offsetTop}, | |
mouse_start = {x: e.clientX, y: e.clientY}; | |
var note_start = {x: editable_new_note.offsetLeft, y: editable_new_note.offsetTop}; | |
document.onmousemove = function(e) | |
{ | |
var mouse_now = {x: e.clientX, y: e.clientY}; | |
div.style.left = (marker_start.x + mouse_now.x - mouse_start.x) + 'px'; | |
div.style.top = (marker_start.y + mouse_now.y - mouse_start.y) + 'px'; | |
editable_new_note.style.left = (note_start.x + mouse_now.x - mouse_start.x) + 'px'; | |
editable_new_note.style.top = (note_start.y + mouse_now.y - mouse_start.y) + 'px'; | |
} | |
return false; | |
} | |
var marker = this; | |
img.onmouseup = function(e) | |
{ | |
var marker_end = {x: div.offsetLeft + .5 * marker_width, y: div.offsetTop + .5 * marker_height}; | |
marker.location = map.pointLocation(marker_end); | |
data.lat = marker.location.lat.toFixed(6); | |
data.lon = marker.location.lon.toFixed(6); | |
document.onmousemove = null; | |
return false; | |
} | |
// add it to the map | |
this.updatePosition = function() | |
{ | |
console.log(marker_width, marker_height); | |
var point = map.locationPoint(marker.location); | |
div.style.left = point.x + - .5 * marker_width + 'px'; | |
div.style.top = point.y - .5 * marker_height + 'px'; | |
if (note_displayed) | |
{ | |
//var marker_width = 30; | |
var offsetY = 5; | |
var editable_new_note = document.getElementById('new_marker_note'); | |
//console.log(div.offsetLeft,editable_new_note.offsetWidth,marker_width); | |
editable_new_note.style.left = div.offsetLeft - .5*editable_new_note.offsetWidth + .5*marker_width + 'px'; | |
editable_new_note.style.top = div.offsetTop - editable_new_note.offsetHeight - offsetY + 'px'; | |
} | |
} | |
map.addCallback('panned', this.updatePosition); | |
map.addCallback('zoomed', this.updatePosition); | |
this.updatePosition(); | |
var ok_button = document.getElementById('new_marker_ok_button'); | |
ok_button.onclick = submitNote; | |
var remove_button = document.getElementById('new_marker_delete_button'); | |
remove_button.onclick = removeMarkerNote; | |
var editable_new_note_textarea = document.getElementById('new_marker_textarea'); | |
editable_new_note_textarea.onchange = function () { | |
data.note = this.value; | |
}; | |
return [this, div]; | |
} | |
for(var rd=0;rd<reddots.length;rd++){ | |
// reduce red dots so they must be >10px from each other | |
var nearRed = false; | |
for(var r2=0;r2<rd;r2++){ | |
var dist = Math.pow((reddots[rd][0] - reddots[r2][0]),2) + Math.pow((reddots[rd][1] - reddots[r2][1]), 2); | |
if(dist < 100){ | |
nearRed = true; | |
break; | |
} | |
} | |
if(nearRed){ | |
continue; | |
} | |
var myloc = map.pointLocation( { x: reddots[rd][0], y: reddots[rd][1] } ); | |
mark(myloc); | |
} | |
for(var rd=0;rd<bluedots.length;rd++){ | |
// reduce blue dots so they must be >10px from each other | |
var nearBlue = false; | |
for(var r2=0;r2<rd;r2++){ | |
var dist = Math.pow((bluedots[rd][0] - bluedots[r2][0]),2) + Math.pow((bluedots[rd][1] - bluedots[r2][1]), 2); | |
if(dist < 100){ | |
nearBlue = true; | |
break; | |
} | |
} | |
if(nearBlue){ | |
continue; | |
} | |
var myloc = map.pointLocation( { x: bluedots[rd][0], y: bluedots[rd][1] } ); | |
mark(myloc); | |
} | |
function mark(myloc){ | |
var marker_width = 30; | |
var marker_height = 30; | |
changeNoteButtonStyle('marker'); | |
var markerInfo = new MarkerNotePlus(map, post_url); | |
var markerSelf = markerInfo[0]; | |
var markerDiv = markerInfo[1]; | |
document.getElementById('marker-container').appendChild(markerDiv); | |
var editable_new_note = document.getElementById('new_marker_note'); | |
editable_new_note.className = 'show'; | |
//var marker_width = 30; | |
var offsetY = 5; | |
editable_new_note.style.position = "absolute"; | |
editable_new_note.style.left = markerDiv.offsetLeft - .5*editable_new_note.offsetWidth + .5*marker_width + 'px'; | |
editable_new_note.style.top = markerDiv.offsetTop - editable_new_note.offsetHeight - offsetY + 'px'; | |
active_marker = true; | |
note_displayed = true; | |
markerSelf.location = myloc; | |
markerSelf.data.lat = markerSelf.location.lat.toFixed(6); | |
markerSelf.data.lon = markerSelf.location.lon.toFixed(6); | |
markerSelf.updatePosition(); | |
} | |
// collect the markers and restyle them | |
// catch new markers and give them the same style | |
var markers = document.getElementsByClassName("marker"); | |
var markerLength = 0; | |
setInterval( function(){ | |
if( markers.length > markerLength ){ | |
var oldMarkerLength = markerLength; | |
markerLength = markers.length; | |
for(var m=oldMarkerLength; m<markers.length; m++){ | |
markers[m].children[0].src = "http://i.imgur.com/fxQyD.png"; | |
markers[m].children[0].onmouseover = function(e){ | |
if (active_polygon == -1 && !active_marker && !draw_mode){ | |
//img.src = 'img/icon_x_mark_hover.png'; | |
if(data.created){ | |
var date = new Date(data.created*1000); | |
var day = date.getDate(); | |
var month = date.getMonth(); | |
var year = date.getFullYear(); | |
var formatted_date = (parseInt(month) + 1) + '/' + day + '/' + year; | |
saved_note.innerHTML = data.note + '<br><br>' + user + ', ' + formatted_date; | |
} | |
else{ | |
saved_note.innerHTML = data.note; | |
} | |
//var marker_width = 30; | |
var offsetY = 5; | |
saved_note.className = 'show'; | |
saved_note.style.position = "absolute"; | |
saved_note.style.left = div.offsetLeft - .5*saved_note.offsetWidth + .5*marker_width + 'px'; | |
saved_note.style.top = div.offsetTop - saved_note.offsetHeight - offsetY + 'px'; | |
} | |
else{ | |
img.style.cursor = 'default'; | |
} | |
}; | |
markers[m].children[0].onmouseout = function(e){ | |
if (active_marker) { | |
return; | |
} | |
//img.src = 'img/icon_x_mark.png'; | |
img.style.cursor = 'move'; | |
if (saved_note.className = 'show'){ | |
saved_note.className = 'hide'; | |
} | |
}; | |
} | |
} | |
}, 250); | |
// have marker tool match new marker icon | |
document.getElementById("marker_button").style.background = 'url("http://i.imgur.com/fxQyD.png") no-repeat'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment