How to make created Draw visible before mouse is moving - openlayers-3

Is there a way to enfore a just created Draw interaction to visualize itself before the first mousemouse event?
I use openlayers 4.6.5. The application creates an ol.interaction.Draw in response to a keyboard event. The type is a LineString.
After the first mousemove the expected circle is shown at the mouse position.
My problem is that the Draw interaction does not visualize anything until the first mouse move by the user.

Interactions are driven by mouse events so you will need to re-run the last event.
Add a listener for pointermove events to your map and save the last one
var lastEvent;
map.on('pointermove', function(event){ lastEvent = event; });
then when you add the interaction get it to handle the last event
map.addInteraction(draw);
draw.handleEvent(lastEvent);
Version 4.6.4 works for me. An interaction is added by after 5 seconds, then removed and new interaction added at 5 and 10 seconds intervals:
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var source = new ol.source.Vector();
var vector = new ol.layer.Vector({
source: source
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4
})
});
var draw; // global so we can remove it later
function addInteraction() {
draw = new ol.interaction.Draw({
source: source,
type: 'LineString'
});
map.addInteraction(draw);
}
var lastEvent;
map.on('pointermove', function(event){ lastEvent = event; });
var add = false;
setInterval(function(){
add = !add;
if (add) {
addInteraction();
draw.handleEvent(lastEvent);
} else {
map.removeInteraction(draw);
}
}, 5000);
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.6.4/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/4.6.4/ol.js"></script>
<div id="map" class="map"></div>

Related

A-Frame + AR.js: How to add objects dynamically in Arjs when tapping on screen?

I'm currently working on an A-Frame AR app by using ar.js (I have to use ar.js). The goal is to dynamically add objects to the scene when tapping on the scene. Unfortunately nothing seems to work out. I managed to change the colors of an existing object when tapping on the screen but not adding a new one. Could someone please help me out here? I would be really grateful!
AFRAME.registerComponent('cursor-listener', {
init: function () {
var currentEl = this.el;
currentEl.addEventListener("click", function (evt) {
console.log("I was clicked!");
currentEl.setAttribute('material', {"color": "blue"});
var el = document.createElement("a-entity");
el.setAttribute('geometry', { "primitive": "sphere", "radius": "1" });
el.setAttribute('position', this.el.object3D.position)
const randomYRotation = Math.random() * 360
el.setAttribute('rotation', `0 ${randomYRotation} 0`)
el.setAttribute('visible', 'true')
el.setAttribute('shadow', {receive: false})
this.el.sceneEl.appendChild(el);
});
},
});
this.el.sceneEl.appendChild(el);
You should append the element to the marker node, and treat it as your "root" element - as it's the one being tracked when detected by camera:
<script>
AFRAME.registerComponent('cursor-listener', {
init:function () {
const marker = document.querySelector("a-marker")
var el = document.createElement("a-sphere");
marker.appendChild(el);
}
})
</script>
<!-- scene and stuff -->
<a-marker preset="hiro>
</a-marker>

OpenLayers: get pixel color from image layer

I have a simple map with a static pixel image layer:
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.13.0/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.13.0/build/ol.js"></script>
// reference to jquery here
</head>
<body>
<div id="map" class="map"></div>
<script>
var extent = [0, 0, 2000000, 2000000];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
image = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: 'http://imgs.xkcd.com/comics/online_communities.png',
projection: projection,
imageExtent: extent
})
});
map.addLayer(image);
image.on('singleclick', function(evt) {
var xy = evt.pixel;
console.log(xy);
var canvasContext = $('.ol-unselectable')[0].getContext('2d');
var pixelAtClick = canvasContext.getImageData(xy[0], xy[1], 1, 1).data;
var red = pixelAtClick[0]; // green is [1] , blue is [2] , alpha is [4]
});
</script>
</body>
</html>
When clicking on the image I want to get the color of the pixel that I clicked on. As far as I understand the raster source example (http://openlayers.org/en/v3.13.0/examples/raster.html), this is only possible with raster sources so I converted the image into a raster source. (When I add that raster source to the layer, I get the message that this operation is insecure, so I still use the image to show on the map.)
Here (How to get a pixel's color value from an Openlayers 3 layer?) the color is read from evt.context. However, with me evt.context is undefined.
Addendum: There might be several image layers overlaying each other. I need to get the color from a single specific image layer.
So this isn't ideal but might send you along the right lines:
You can use the pixel xy of the click event to query the canvas object that openlayers creates and puts your map data onto.
map.on('singleclick', function(evt) {
var xy = evt.pixel;
var canvasContext = $('.ol-unselectable')[0].getContext('2d');
var pixelAtClick = canvasContext.getImageData(xy[0], xy[1], 1, 1).data;
var red = pixeAtClick[0]; // green is [1] , blue is [2] , alpha is [4]
});
This assumes that you are using jQuery and that the canvas is the first DOM element using the class '.ol-unselectable'.
Hope it helps.

map.on('click') coordinates wrong in Firefox

I am using OpenLayers 3.10.1 and the following code:
map.on('click', function (map, evt) {
var mouseCoords = [evt.originalEvent.offsetX, evt.originalEvent.offsetY];
alert(mouseCoords);
});
When I click as near as I can to the upper left corner of the map in IE or Chrome, I get an alert with the mouse coordinates offset from the top left corner of the map div, i.e. something sensible like [3,4].
But when I try the same things I get the mouse coordinates relative to the browser window and not the map div. Does anyone know why this is? Am I using an outdated way to find the mouse coordinates (ultimately so I can calculate which feature was clicked)?
Some alternatives:
map.on('click', function(evt){
console.info(evt.pixel);
console.info(map.getPixelFromCoordinate(evt.coordinate));
});
The following code works for me (openlayer 4.4, angular 4+)
_initMap() {
console.info("_initMap");
this.mapW = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'myMapDiv',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: new ol.View({
center: ol.proj.fromLonLat([this.lon, this.lat]);,
zoom: 12
})
});
const theMap = this.mapW;
// display on click
this.mapW.on('click', function(evt) {
/* // you want to detect feature click
var feature = theMap.forEachFeatureAtPixel(evt.pixel,
function(feature, layer) {
return feature;
});
if (feature) {
var fname = feature.getProperties().name;
console.info("feature clicked:" + fname);
return;
}
*/
console.info(evt.coordinate);
console.info(ol.proj.toLonLat(evt.coordinate)); // <=== coordinate projection
});
JS console results (when clicking close to Grenoble in France):
(2) [637000.3050167585, 5652336.68427412]
(2) [5.722271099853512, 45.19540527485873]

cannot set renderer on openlayers 3

According to a book I am reading about Openlayers 3 , all I have to do, to reset the renderer is to do this in the Map initialization
renderer: 'dom'
so my code is
var map = new ol.Map({
target: 'map',
layers: [layer],
renderer: 'dom',
view: view,
});
When I load the page, the console gives no errors, but the map does not load at all. I use Openlayers 3.9.0. What is going wrong here?
Thanks
EDIT
This is all the openlayers code
var layer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var kbz = new ol.interaction.KeyboardZoom();
var dr = new ol.interaction.DragRotateAndZoom();
var control = new ol.control.FullScreen();
var center = ol.proj.transform([-1.812, 52.443], 'EPSG:4326', 'EPSG:3857');
var we = new ol.Overlay({
position: center,
element: document.getElementById('we')
});
var view = new ol.View({
center: center,
zoom: 6
});
var map = new ol.Map({
target: 'map',
layers: [layer],
renderer: 'dom',
view: view
});
map.addInteraction(kbz);
map.addInteraction(dr);
map.addControl(control);
map.addOverlay(we);
You have to set the size of the map target element, when using the dom renderer.
Canvas elements, which are used by the default renderer, has a default height of 150px, while normal divs don't have a default height. Setting the height of the target should make you map appear:
#map {
height: 200px;
}

Why is my Google Map in a jQuery UI tab only displaying one tile at the top left corner of the screen?

I have two Google Map API v3 Maps in jQuery tabs. They both display the first time they appear in their tabs, but the initially deselected tab only displays a tile or so at the top left-hand corner.
Calling google.maps.event.trigger(all_map, 'resize') periodically does not change this.
In my code I have:
<div id='all_map_canvas'>
</div>
<script>
function show_all_map()
{
var center = new google.maps.LatLng(%(center_latitude)s - .15, %(center_longitude)s + .2);
var myoptions = {
zoom: %(zoom)s,
center: center,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
all_map = new google.maps.Map(document.getElementById('all_map_canvas'), myoptions);
all_map.setZoom(%(zoom)s);
jQuery('#all_map_canvas').show();
google.maps.event.trigger(all_map, 'resize');
}
function show_all_map_markers()
{
%(all_map_markers)s
}
var markers = [];
jQuery('#all_map_canvas').width(jQuery(window).width() - 300);
jQuery('#all_map_canvas').height(jQuery(window).height() - 125);
How can I make both maps display in full after tab swaps?
I had the same problem: Google map in div that has style display:none;.
Solved it with this two steps:
Removing all additional styling of the div I'm placing the map except height:100%;
Initiate the map after the holding div is displayed not when the it is created. In my case in the callback function of the show method:
CSS
.main-window #map{
height:100%;
}
JS
$('.main-window').show(3000, function() {
// create the map after the div is displayed
var mapOptions = {
center: new google.maps.LatLng(42.499591, 27.474961),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
});
HTML
<div class="main-window">
<div id="map"></div>
</div>
Initiating it in events like jQuery's '$(document).ready(...' or Google's 'google.maps.event.addDomListener(window, "load", ...' is not working for some reason.
Hope it helps.
I am using gmaps.js which is a simplified api for google map. But it's simply a matter of attaching a tabsshow event in javascript and refreshing the map in the delegate's function.
Here's the code I use for gmaps.js
$('#tabs').bind('tabsshow', function(event, ui) {
event.preventDefault();
if (ui.panel.id == "tabs2") {
//gmaps.js method
map.refresh();
map.setCenter(lastLoc.lat(), lastLoc.lng());
//for native google.maps api
google.maps.event.trigger(map, 'resize');
map.panTo(new google.maps.LatLng(lastLoc.lat(), lastLoc.lng()));
}
});

Resources