Using Flag Sprites in Google Earth - javascript

So I've been using the Google Earth API and have attempting to change the image of the place marks upon mouseover.
I would like to use flag-sprites to minimize the load but I'm having trouble working out the syntax. The usage is pretty straight forward if I were to drop it straight into the HTML file.
Example:
<img src="blank.gif" class="flag flag-cz" alt="Czech Republic" />
But when it comes to putting it into my javascript file, I'm a bit lost. Here's my code:
var placemark = ge.createPlacemark('');
placemark.setName(country.name);
ge.getFeatures().appendChild(placemark);
google.earth.addEventListener(placemark, "mouseover", function(event){
placemark.setAttribute("class", "flag flag-cz");
placemark.setAttribute("alt", "Czech Republic");
placemark.setAttribute("src", "blank.gif");
});
I also attempted to do this using the highlightIcon technique but the "setAttribute" method breaks the code (since highlightIcon is a different variable type than placemark):
//Create highlight style for style map.
var highlightStyle = ge.createStyle('');
var highlightIcon = ge.createIcon('');
highlightIcon.setHref('http://google-maps-icons.googlecode.com/files/world.png');
highlightIcon.setAttribute("class", "flag flag-cz");
highlightIcon.setAttribute("alt", "Czech Republic");
highlightIcon.setAttribute("src", "blank.gif");
highlightStyle.getIconStyle().setIcon(highlightIcon);
highlightStyle.getIconStyle().setScale(15.0);

You can achieve what you want but not with CSS, since GE Plugin lives in a different realm.
First you define the sprite as the Placemark Icon, then you must explicitly set its offset in the X and Y axis.
Something like:
var icon = window.ge.createIcon('');
icon.setHref("http://opengameart.org/sites/default/files/styles/watermarked/public/last-guardian-sprites_0.png");
// Set the size of the ICON - according to the dimension on the sprite
icon.setW(50);
icon.setH(50);
// Set its offset
icon.setX(10);
icon.setY(50);
var placemark = ge.createPlacemark('');
var style = ge.createStyle(''); //create a new style
style.getIconStyle().setIcon(icon); //apply the icon to the style
placemark.setStyleSelector(style); //apply the style to the placemark
// Set the placemark's location.
var point = ge.createPoint('');
point.setLatitude(window.lat);
point.setLongitude(window.lon);
placemark.setGeometry(point);
window.ge.getFeatures().appendChild(placemark);
Also the Y axis begins in the bottom left corner of your Image.
In order to use flag-sprites you will have to re-map all the offsets (x,y), for each country flag, in your code and use those offsets when loading the placemark.
Here is the reference for the KmlIcon: https://developers.google.com/earth/documentation/reference/interface_kml_icon

Related

How to trace / track user input on touch screen to match image on screen

So I want to have an image, let's say a square and would want the user to 'trace' the image with their finger, I need to track this and know / understand if the user has done it correctly.
The use case is educational software where users trace shapes to learn how to draw them.
My thinking was an SVG object and then mouse hold events but because SVG has beginning and end points I am not sure if they could then be tracked all the way over the image etc.
Also how? If I have interaction on the SVG is it a matter of if statements and some kind of variance on the line and if user gets to far away from the original line then stop / break?
Sorry if this is explained badly also I couldn't find almost anything so I'm also sorry if this is a duplicate.
Found this article: https://www.smashingmagazine.com/2018/05/svg-interaction-pointer-events-property/
And: https://gist.github.com/elidupuis/11325438 / http://bl.ocks.org/elidupuis/11325438
So could maybe cobble something together but yes any direction would be appreciated.
var xmlns = "http://www.w3.org/2000/svg";
function setMouseCoordinates(event) {
// contains the size of element having id 'image svg' and its position relative to the viewport, svg width/height equal to image height and width
var boundary = document.getElementById('<id_of_image_svg>').getBoundingClientRect();
// sets the x position of the mouse co-ordinate
auth_mouseX = event.clientX - boundary.left;
// sets the y position of the mouse co-ordinate
auth_mouseY = event.clientY - boundary.top;
return [auth_mouseX, auth_mouseY];
}
// add this in mousedown or respective touch event
function drawPath(event) {
var {
auth_mouseX,
auth_mouseY
} = setMouseCoordinates(event);
// Creates an element with the specified namespace URI and qualified name.
scribble = document.createElementNS(xmlns, 'path');
// sets the stroke width and color of the drawing drawn by scribble drawing tool
scribble.style.stroke = 'red';
// sets the stroke width of the scribble drawing
scribble.style.strokeWidth = '2';
scribble.style.fill = 'none';
scribble.setAttributeNS(null, 'd', 'M' + auth_mouseX + ' ' + auth_mouseY);
}
Now you can add this function in the touchdown event and create logic accordingly. You have to check that the user has start or stopped the drawing by a varible and changing its value accordingly.
For evaluation of task whether it is in a given area or not you have to use some shape detection api or AI (You can search on google there are many of them like AWS rekognition and many others I don't remember the name)
Hope it helps anyhow. :)

Class of the UI Control ZOOM in HERE MAPS

When placing the ZOOm control e.g. on the top right corner, the the "+" and "-" are side by side. But what if I want to have them on the top of each other? I made a 'bad' code which works:
$(".H_l_anchor.H_l_horizontal").each(function(index) {
if($(this).html().length>0) {
if($(this).html().indexOf("H_ctl H_el H_zoom H_grp")>0) {
$(this).removeClass("H_l_anchor H_l_horizontal").addClass("H_l_anchor H_l_vertical");
}
}
});
But: is there an elegant way?
The Maps API supports changing the position of the UI controls. In the following example, all map controls are moved to the top-left corner of the map viewport.
The code extends the previous example by obtaining an instance of each of the default UI controls and then setting alignment on the controls to the top-left corner.
var mapSettings = ui.getControl('mapsettings');
var zoom = ui.getControl('zoom');
var scalebar = ui.getControl('scalebar');
mapSettings.setAlignment('top-left');
zoom.setAlignment('top-left');
scalebar.setAlignment('top-left');
Please refer setAlignment more options : https://developer.here.com/documentation/maps/api_reference/H.ui.Control.html#setAlignment
Find detail in reference to control alignment :
https://developer.here.com/documentation/maps/dev_guide/topics/map-controls-ui.html
There is a difference between LEFT_TOP and TOP_LEFT alignments. Here you can see alignments explained: https://developer.here.com/documentation/maps/3.1.12.0/api_reference/H.ui.Control.html#setAlignment
What you want is LEFT_TOP, so:
ui.getControl('zoom').setAlignment(H.ui.LayoutAlignment.LEFT_TOP);
Note: You should not specify parameter as simple string e.g.: 'left-top'. It's not safe.

Leaflet map with popup above legend

I have a situation where I have a map with a custom legend formatted as either an SVG or a PNG. The legend is always placed in the bottom left corner but can be quite large (user can turn it off and on).
The map also has many markers. Each marker will have a tooltip, which can also be large-ish. Tooltips show when the mouse is hovering over the marker. The problem arises when a user hovers over a marker close to the legend - the tooltip appears behind the legends. I'd like to make it so the popups appear above the legend. So, from bottom to top: marker, legend, marker popup.
Here is a JSFiddle https://jsfiddle.net/e51mydwa/9/ to describe what I mean. I add the legends in the same way, although the < div id="legend"> tag contains a < img> or < svg> in reality.
<div id="map">
<div id="legend">
I am Legend
</div>
</div>
I've had a look at http://leafletjs.com/examples/choropleth/ , but as you can see by inspecting the DOM, this will suffer the same problem, as the legend is added into the same div as the leaflet controls, which is always above the map layers (as it should be, controls should always be at the top).
I've also tried inserting the legend into a div which is on a sibling layer to the popup containing layer. This fixes the z-index issue, however the parent div of both of these contains a transform which changes as the user drags the map around - meaning the legends change places and aren't static.
Any and all suggestions appreciated.
This requires some heavy hacking, due to the architecture of the Leaflet layers and controls.
One possible approach is to make a custom layer class which stays in a static position, by repositioning its pixel offset at every change of the map's view.
I heartily recommend reading the Leaflet tutorials, in particular the one about map panes and the one about custom layers, to understand how this works.
// Create a 'static' map pane
L.Map.addInitHook(function(){
this.createPane('static');
this.getPane('static').style.zIndex = 675;
});
// Define a custom layer class
L.Layer.StaticOverlay = L.Layer.extend({
onAdd: function(map) {
this._map = map;
var pane = map.getPane('static');
this._container = L.DomUtil.create('div');
pane.appendChild(this._container);
// styling, content, etc
this._container.style.background = 'white';
this._container.style.width = '100px';
this._container.style.height = '50px';
this._container.innerHTML = 'Hi!'
map.on('move zoom viewreset zoomend moveend', this._update, this);
this._update();
},
onRemove: function(map) {
L.DomUtil.remove(this._container);
map.off('move zoom viewreset zoomend moveend', this._update, this);
},
_update: function() {
// Calculate the offset of the top-left corner of the map, relative to
// the [0,0] coordinate of the DOM container for the map's main pane
var offset = map.containerPointToLayerPoint([0, 0]);
// Add some offset so our overlay appears more or less in the middle of the map
offset = offset.add([340, 220]);
L.DomUtil.setPosition(this._container, offset);
}
});
When that's defined, you can simply
var static = new L.Layer.StaticOverlay().addTo(map);
Obviously there are some bits missing, such as how to position the overlay properly (get the map pixel size with getSize(), do the proper arithmetic), and how to set the contents of the overlay with some custom options in the layer constructor.
These are left as an exercise to the reader :-)
See a working example here.

Google Maps custom content boxes?

I can't seem to find andthing in the Google Maps V3 docs about creating custom content boxes for Google maps.
Below is an example of a custom content box:
http://www.apple.com/retail/alamoana/map/
My question is... how do you go about changing the default white balloon popup?
Cheers!
Look at the InfoBox toolkit in the v3 utility libraries. I'm using them on dev.mapfaire.com, if you want to take a look.
Personally, i don't use any of google's custom overlay scripts and such. I made a custom php page which hold the iframe, where I can load custom css files, and also I create custom DIVs that go over top of the map, which are then repositioned while dragging when opened.
You can use the "Drag,Dragstart,Dragend" events to help you reposition elements that you have created.
If you have custom markers set onto you page you can get their pixel position with this function:
getPosition: function (marker) {
var map = this.map /* Your map, in my case is part of my controller object linked to this.map */;
var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(
map.getBounds().getNorthEast().lat(),
map.getBounds().getSouthWest().lng()
);
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(marker.getPosition());
var pixelOffset = new google.maps.Point(
Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
);
return pixelOffset; /* Returns the top left pixel of the specified marker on the specified map */
}
And then I use a setPosition function which is used when the window is dragging, it sets your custom element's position to the marker's position.
The dragging event can be set in such manner:
google.maps.addEventListener(map,'drag',function () { setPosition(marker,element); });
The setPosition Function simply gathers the width,height of the element, and the pixel offset associated to the marker using the getPosition(marker) function:
setPosition: function (marker,element) {
var p = this.getPosition(marker),
s = {width:element.offsetWidth,height:element.offsetHeight},
markerOffset = {width:58,height:58};
element.style.left = p.x - (s.width/2) + (markerOffset.width/2) + "px"; /* We set the element's left position to the marker's position + half of our element's width + half of the marker's width's so it is centered */
element.style.top = p.y - s.height - (markerOffset.height) + 10 + "px"; /* We set the element's top position to the marker's position + our element's height + markers height so it is 10px above our marker vertically */
},
Sometimes you just have to think a bit outside the box
That example is using the second version of google maps. That features might not be available in the 3rd one.
But you can add any html code in the infowindows and personalize them. I'm not sure if you can change how they look directly, but you can definitely change how the content looks like.
Edit: I found some sample code: http://gmaps-samples-v3.googlecode.com/svn/trunk/infowindow_custom/infowindow-custom.html
Take a look at gmaps-utility-library-dev and more specific in the ExtInfoWindow utility and PopupMarker utility
As Sudhir pointed out, the Infobox Plugin is one way to do what you want. I've recently answered a similar question about using the infobox plugin for google maps api 3 and provided a complete example.

How to display an overlay label on a chart?

I have a chart created with Birt and I want to add some label on it to specify the 4 regions delimited by the 2 red markers (see image below), one label in each quadrant (centered if possible).
I am looking for a solution to do that, directly using birt chart editor or by using a javascript (like I have done for the red markers).
In order to dynamically center some type of label in each quadrant of the graph, you'll have to have some way of calculating the coordinates. Of course, I'm not really familiar with Birt and I'm making the assumption that the graph's red markers will vary.
Anyway, assuming that you can get the coordinates, you could write a function that would dynamically generate the label based on a couple of parameters:
function generateLabel(sContent, iXoffset, iYoffset) {
var eLabel = document.createElement('span');
eLabel.appendChild(document.createTextNode(sContent));
var eDivision = document.createElement('div');
eDivision.appendChild(eLabel);
eDivision.style.left = iXoffset + 'px';
eDivision.style.top = iYoffset + 'px';
// include other styles here...
return eDivision;
}
and then from there, you can call this function with the set label content and offset coordinates:
var eQuadrantOneLabel = generateLabel('Quadrant One', 10, 25);
// and so on...
Then just add the element to the graph's container (assuming that is has an id of, say, graph):
var eGraphContainer = document.getElementById('graph');
eGraphContainer.appendChild(eQuadrantOneLabel);
// and so on for each label...

Categories

Resources