Kendo UI (Graph) Add relief to the bubbles on the Bubble chart - css

I was wondering if it's possible to add a relief to the bubbles on the Kendo UI Bubble charts, because, with the 15 given themes, all bubbles stay flat :
http://demos.telerik.com/kendo-ui/bubble-charts/index
It would be nice to add a 3D-style like the pie chart (Uniform style):
http://demos.telerik.com/kendo-ui/pie-charts/index
I guess it could be done by adding a CSS to the SVG, but I'm kind of lost.
Any ideas ?
Thanks :D

A colleague of mine found a solution. You have to call this code after every refresh or draw call :
var svg = $('svg');
var circles = svg.find('circle');
var svgEl = svg[0];
$.each(circles, function (key, circle) {
var fillColor = $(this).attr('fill');
var id = fillColor.replace('#', 'kgrad');
var stops = [
{offset: '0', 'stop-color': fillColor, 'stop-opacity': 0.3},
{offset: '0.84', 'stop-color': fillColor, 'stop-opacity': 0.95},
{offset: '0.85', 'stop-color': fillColor, 'stop-opacity': 0.7},
{offset: '0.99', 'stop-color': fillColor, 'stop-opacity': 1}];
if (svg.find('#' + id).length === 0) {
var svgNS = svgEl.namespaceURI;
var grad = document.createElementNS(svgNS, 'radialGradient');
grad.setAttribute('id', id);
for (var i = 0; i < stops.length; i++) {
var attrs = stops[i];
var stop = document.createElementNS(svgNS, 'stop');
for (var attr in attrs) {
if (attrs.hasOwnProperty(attr))
stop.setAttribute(attr, attrs[attr]);
}
grad.appendChild(stop);
}
var defs = svgEl.querySelector('defs') || svgEl.insertBefore(document.createElementNS(svgNS, 'defs'), svgEl.firstChild);
defs.appendChild(grad);
}
$(this).attr('fill', 'url(#' + id + ')');
}, this);

Related

How do I draw a marker or a circle on a Google StreetViewPanorama

I am creating a walkthrough for the interior of a building and am wondering how to draw a marker on a StreetViewPanorama. Maybe I'm missing something basic, but everything I have read indicates that you need a lat and lng to draw the marker.
Here is what I have:
var initPosPanoID, streetView;
function initPano() {
// Set StreetView provider.
var streetViewOptions = {
zoom: 0,
panoProvider: getCustomPanorama,
pano : "lobby",
addressControlOptions: {
position: google.maps.ControlPosition.BOTTOM_CENTER
}
};
// Create a StreetView object.
var streetViewDiv = document.getElementById('map');
streetView = new google.maps.StreetViewPanorama(streetViewDiv, streetViewOptions);
// Add links when it happens "links_change" event.
google.maps.event.addListener(streetView, "links_changed", createCustomLink);
google.maps.event.addListener(streetView, "pano_changed", function() {
var panoCell = document.getElementById('pano-cell');
panoCell.innerHTML = panorama.getPano();
});
}
function getCustomPanoramaTileUrl(panoID, zoom, tileX, tileY) {
// Return a pano image given the panoID.
return "images/he/" + panoID + '.jpg';
}
function getHeading(panoID) {
var heading;
switch(panoID) {
case "lobby":
heading = 0;
break;
case "secorner":
heading = 100;
break;
}
return heading;
}
function getCustomPanorama(panoID) {
// get a custom heading for the pano
var heading = getHeading(panoID);
var streetViewPanoramaData = {
links: [],
copyright: 'Imagery (c) HumanElement',
tiles: {
tileSize : new google.maps.Size(1024, 512),
worldSize : new google.maps.Size(1024, 512),
// The heading in degrees at the origin of the panorama
// tile set.
centerHeading : heading,
getTileUrl : getCustomPanoramaTileUrl
}
};
switch(panoID) {
case "lobby":
// Description of this point.
streetViewPanoramaData["location"] = {
pano: 'lobby',
description: "Human Element",
latLng: new google.maps.LatLng(42.282138, -83.751471)
};
return streetViewPanoramaData;
case "secorner":
streetViewPanoramaData["location"] = {
pano: 'secorner',
description: "SouthEast Corner",
latLng: new google.maps.LatLng(42.282078, -83.751413)
};
return streetViewPanoramaData;
}
}
function createCustomLink() {
var links = streetView.getLinks();
var panoID = streetView.getPano();
switch(panoID) {
case "lobby":
links.push({
description : "SouthEast Corner",
pano : "secorner",
heading : 280
});
break;
case "secorner":
links.push({
description : "HumanElement Lobby",
pano : "lobby",
heading : 90
});
break;
}
}
I would like to have different markers or touchpoints at different locations, but am not sure how to get them on there.
Trying to draw a standard marker does not work without the lat/lng.
I thought about trying to create it around a google.maps.Point thinking I might be able to use the x and y from my tiles, but couldn't seem to get that working.
The other options I see are related to google.maps.drawing.DrawingManager.
Does anyone have any advice on this?
Setting up the map this way helped: It creates the map and panorama separately and then sets the panorama into the map, rather than just having the panorama object by itself.
map = new google.maps.Map(document.getElementById('map'), {
center: position,
zoom: 10
});
// Create the panorama and set it into the map
panorama = new google.maps.StreetViewPanorama(
document.getElementById('map'), {
position: position,
pov: {
heading: 0,
pitch: -10
},
// Override the default panoId to outside the building to start
pano:'e_giRekRylYAAAQn7y2xAg'
});
map.setStreetView(panorama);
For placing markers on the map, I found an excellent plugin which creates points and then places elements on those points.
https://github.com/marmat/google-maps-api-addons/tree/master/panomarker
So far this is working very well. If you have an interior walkthrough, you should be able to toggle markers based on the PanoId. You can even add click listeners to open up dialogs.

Google Map Hybrid and Aerial tiles missing

I am using google map api. I am having an issue with Google base map. When i load Google hybrid or aerial, it gives me following result.
https://www.dropbox.com/s/u51hegt7hu03gz9/Untitled.png?dl=0
Some tiles are missing on the map.
Missing tiles: https://www.dropbox.com/s/5vlp86xf4iote32/Untitled2.png?dl=0
My code is:
google.maps.event.addListener(mapA, 'maptypeid_changed', function () {
var mapTypeId = mapA.getMapTypeId();
if (mapTypeId != "basemap")
mapTileSource = [];
if (mapTypeId == google.maps.MapTypeId.HYBRID) {
mapTileSource.push("http://khm1.google.com/kh/v=134&x={0}&y={1}&z={2}&s=Gal");
mapTileSource.push("http://mt0.google.com/vt/lyrs=h#177290279&hl=en&x={0}&y={1}&z={2}&s=Gal");
}
else if (mapTypeId == google.maps.MapTypeId.ROADMAP) {
mapTileSource.push("http://mt1.google.com/vt/lyrs=m#113&hl=hu&x={0}&y={1}&z={2}&s=Gal");
}
else if (mapTypeId == google.maps.MapTypeId.SATELLITE) {
mapTileSource.push("http://khm1.google.com/kh/v=134&x={0}&y={1}&z={2}&s=Gal");
}
else if (mapTypeId == google.maps.MapTypeId.TERRAIN) {
mapTileSource.push("http://mt1.google.com/vt/lyrs=t#131,r#176163100&hl=en&x={0}&y={1}&z={2}&s=Gal");
}
});
Some tiles are missing on the view.
I have tried this:
function CoordMapType(tileSize) {
debugger;
this.tileSize = tileSize;
}
CoordMapType.prototype.getTile = function (coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('div');
div.innerHTML = coord;
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
div.style.borderStyle = 'solid';
div.style.borderWidth = '1px';
div.style.borderColor = '#AAAAAA';
return div;
};
mapA.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(256, 256)));
And i have also tried this:
google.maps.event.addListenerOnce(mapA, 'tilesloaded', function() {
google.maps.event.addListenerOnce(mapA, 'tilesloaded', function() {
google.maps.event.trigger(mapA, 'resize');
});
});
But they did not work for me.
Can anyone please tell me the way to load all the tiles on the map?
Thank you
Try set higher version (the number after m# or h# etc.) and use url directly in web broswer (check if tile in this version exists)
http://mt1.google.com/vt/lyrs=m#901000000&hl=en&x=4&y=10&z=5&s=Ga
or check your cache layer (if you use)
In my option for googleSatellite :
get error - http://khm0.google.com/kh/v=149&hl=en&x=18&y=9&z=5&s=Galileo
******* ok - http://khm0.google.com/kh/v=165&hl=en&x=18&y=9&z=5&s=Galileo
Here's a working example of mapbox with google maps hybrid satellite view: https://github.com/SnakeO/mapbox-with-google-maps-hybrid-tiles

OpenLayers 3 icons projection

I'm making a map with OpenLayers 3, I have coordinates (EPSG:3857) in PostgreSQL and the map layer is OSM (same projection that the icons, EPSG:3857).
The problem is that when I increment the zoom, the icons disappear... But if I decrement then the icons won't disappear.
Someone told me that the projection's ICONS and LAYER must be the same.
Can someone help me, please?
I'm new in StackOverFlow,
Thank you for your time,
Enrique.
Note: My code is in JSFiddle, can see here: jsfiddle.net/y3sLksg6/
Try to set the style to each of your markers individually as in the exaple below, which is a copy from your jsfiddle:
function AddMarkers() {
//create a bunch of icons and add to source vector
var sizeY = Object.size(coordenadas);
var x = null;
var y = null;
for (var i = 0; i < sizeY; i++) {
x = coordenadas[i].Longitude;
y = coordenadas[i].Latitude;
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point([x, y]),
name: 'Marker ' + i,
population: 4000,
rainfall: 500
});
markers[i] = [x, y];
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: './img/circleRed.png'
}))
});
// This is new !
iconFeature.setStyle(iconStyle);
vectorSource.addFeature(iconFeature);
}
return vectorLayer;
}

AmCharts map - insert html

I'm trying to create a pulse effect on a point on a AmCharts Map. In order to do this I need to insert HTML at a latitude and longitude point but can't work out how to do it through the api (http://docs.amcharts.com/3/javascriptmaps/)
Here is the effect I'm trying to achieve - http://kevinurrutia.tumblr.com/post/16411271583/creating-a-css3-pulsating-circle
Here is a jsfiddle of the map with the HTML and CSS http://jsfiddle.net/9cBXh/2/
// request #3275
var dataPoints = [{
latitude: '51.000000000000',
longitude: '9.000000000000',
type: 'bubble',
color: '#cc0000',
fixedSize: false,
alpha: 0.9,
height: 30,
width: 30,
centered: true,
id: 'test'
}];
AmCharts.ready(function() {
// create AmMap object
var map = new AmCharts.AmMap();
// set path to images
map.pathToImages = "http://www.ammap.com/lib/images/";
var dataProvider = {
mapVar: AmCharts.maps.worldLow,
getAreasFromMap:false,
images: dataPoints
};
// pass data provider to the map object
map.dataProvider = dataProvider;
map.areasSettings = {
autoZoom: true,
selectedColor: "#CC0000"
};
// write the map to container div
map.write("mapdiv");
});
The red dot is the bubble generated through the api. The blue dot and circle is the html I need to insert at the lat and long co-ordinates...somehow!
Any help would be appreciated.
Here's a complete working example of the AmCharts map with several pulsating HTML elements as map markers:
http://www.amcharts.com/demos/custom-html-elements-map-markers/
(You can view the source by clicking on the EDIT button)
The idea is very simple:
Trap "positionChanged" event. Go throiugh all of the "images" in the map's dataProvider, create HTML elements for each of those, then position them directly over the map by using API functions that resolve longitude/latitude coordinates to screen top/left coordinates:
// add events to recalculate map position when the map is moved or zoomed
map.addListener("positionChanged", updateCustomMarkers);
// this function will take current images on the map and create HTML elements for them
function updateCustomMarkers (event) {
// get map object
var map = event.chart;
// go through all of the images
for( var x in map.dataProvider.images) {
// get MapImage object
var image = map.dataProvider.images[x];
// check if it has corresponding HTML element
if ('undefined' == typeof image.externalElement)
image.externalElement = createCustomMarker(image);
// reposition the element accoridng to coordinates
image.externalElement.style.top = map.latitudeToY(image.latitude) + 'px';
image.externalElement.style.left = map.longitudeToX(image.longitude) + 'px';
}
}
// this function creates and returns a new marker element
function createCustomMarker(image) {
// create holder
var holder = document.createElement('div');
holder.className = 'map-marker';
holder.title = image.title;
holder.style.position = 'absolute';
// create dot
var dot = document.createElement('div');
dot.className = 'dot';
holder.appendChild(dot);
// create pulse
var pulse = document.createElement('div');
pulse.className = 'pulse';
holder.appendChild(pulse);
// append the marker to the map container
image.chart.chartDiv.appendChild(holder);
return holder;
}

Changing Google Maps v3 MarkerClustererPlus Title

I am trying to dynamically set the cluster title, rollover text, of clustered icons. I want the cluster count/total to be used in the rollover text.
Through console.log I am able to see that the title has been changed to that set for var txt. It also works with alert( txt ). The default title for a cluster is "" and does not seem to be getting updated and stays at the default value.
Currently I am setting the title in google.maps.event.addListener( markerClusterer, 'mouseover', function( cluster ) {}).
I'm thinking that my code continues to execute and that might be the reason I don't see the change but I haven't been able to narrow it down.
var latlng = new google.maps.LatLng( lat, lng );
var qs = location.search;
var options = {
zoom: 17,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
};
map = new google.maps.Map( mapId[0], options );
google.maps.event.addListener( map, 'idle', function() {
var bounds = map.getBounds();
downloadXML( ABSPATH + 'xml/maps/markers.php' + qs + '&bounds=' + bounds, function( data ) {
var xml = parseXml( data );
var markers = xml.documentElement.getElementsByTagName( "marker" );
var markerArray = [];
for ( var i = 0; i < markers.length; i++ ) {
var attributes = getMarkerAttributes( markers[i] );
var marker = createMarker( attributes );
// Add marker to marker array
markerArray.push(marker);
}
// Define the marker clusterer
var clusterOptions = {
zoomOnClick: false,
gridSize: 1
}
var markerClusterer = new MarkerClusterer( map, markerArray, clusterOptions );
// Listen for a cluster to be clicked
google.maps.event.addListener( markerClusterer, 'clusterclick', function( cluster ) {
combineInfoWindows( cluster );
});
// Listen for a cluster to be hovered and set title
google.maps.event.addListener( markerClusterer, 'mouseover', function( cluster ) {
var txt = 'There are ' + cluster.getSize() + ' properties at this location.';
//alert( txt );
console.log( cluster );
markerClusterer.setTitle( txt );
});
}); // downloadXML
}); // google.maps.event.addListener( map, 'idle', ... )
Any help would be greatly appreciated. Thanks!
EDIT: 1
I have a solution based on the suggested solution by Rick.
I have modified the onAdd method.
/**
* Adds the icon to the DOM.
*/
ClusterIcon.prototype.onAdd = function () {
var cClusterIcon = this;
// MY CHANGES - START
this.cluster_.markerClusterer_.title_ = 'There are ' + this.cluster_.getSize() + ' properties at this location.';
// MY CHANGES - END
this.div_ = document.createElement("div");
if (this.visible_) {
this.show();
}
...
};
EDIT: 2 - FINAL SOLUTION
Moved changes to show method versus previous onAdd method as Rick had suggested. Change is made in a file outside of the original source file for MarkerClustererPlus.
/**
* Positions and shows the icon.
*/
ClusterIcon.prototype.show = function () {
if (this.div_) {
var pos = this.getPosFromLatLng_(this.center_);
this.div_.style.cssText = this.createCss(pos);
if (this.cluster_.printable_) {
// (Would like to use "width: inherit;" below, but doesn't work with MSIE)
this.div_.innerHTML = "<img src='" + this.url_ + "'><div style='position: absolute; top: 0px; left: 0px; width: " + this.width_ + "px;'>" + this.sums_.text + "</div>";
} else {
this.div_.innerHTML = this.sums_.text;
}
//this.div_.title = this.cluster_.getMarkerClusterer().getTitle();
// MY SOLUTION BELOW
this.div_.title = 'There are ' + this.cluster_.getSize() + ' properties at this location.';
this.div_.style.display = "";
}
this.visible_ = true;
};
Are you using this for clustering markers? Did you extend it to make your own setTitle function? If not, You'll have to make your own label. It's not actually a marker per se.
Edit: Didn't know this existed.
The cluster icons just pull the title from the MCOptions. I don't see where ClusterIcon or Cluster has a setTitle function, so I'd think the best bet would be overriding the ClusterIcon show prototype yourself and setting it there.
> ClusterIcon.prototype.show =
> function () { if (this.div_) {
> var pos = this.getPosFromLatLng_(this.center_);
> this.div_.style.cssText = this.createCss(pos);
> if (this.cluster_.printable_) {
> // (Would like to use "width: inherit;" below, but doesn't work with MSIE)
> this.div_.innerHTML = "<img src='" + this.url_ + "'><div style='position: absolute; top: 0px; left: 0px; width: " + this.width_
> + "px;'>" + this.sums_.text + "</div>";
> } else {
> this.div_.innerHTML = this.sums_.text;
> }
> this.div_.title = **** Your stuff here ***
> this.div_.style.display = ""; } this.visible_ = true; };
Your problem is that you are trying to assign the mouseover event listener (where you set the title) to a MarkerClusterer, but to define a mouseover listener, you have to pass a Cluster.
There is a MarkerClusterer.getClusters() function that will return an Array of the Cluster instances. You want to loop over that Array and pass an instance of Cluster to your mouseover event listeners. If you check the reference doc and scroll down to the MarkerClusterer Events section of the doc, the row for mouseover defines the Argument to be:
c:Cluster
Which is in contrast to events like clusteringbegin and clusteringend, which define the Argument to be:
mc:MarkerClusterer
Having said all that, I'm not sure there is an easy way to set the title for each Cluster. That class does not have a setTitle function. The setTitle on the MarkerClusterer just applies the title to all of the Cluster instances. And I've double checked in JavaScript; there is no setTitle function on the Cluster class. Your best option right now seems to be to dynamically create the content you want to display within the mouseover handler for each Cluster. You could create an InfoBox and then close it on a Cluster mouseoet event. Not the simplest solution ever, but it will get you where you want to be.
I know this is an old question, but it ranked high on Google for my search. Anyway, here is what I did thanks to tips from this page:
google.maps.event.addListener(markerCluster, 'mouseover', function (c) {
if(c.clusterIcon_.div_){
c.clusterIcon_.div_.title = c.getSize() + ' businesses in this area';
}
});
I can't guarantee it will be compatible with future versions of MarkerClusterer Plus since I'm using "private" properties clusterIcon_ and div_.

Resources