I was wondering if it would be possible to animate the heat map I've set up for my Google Map. It was easy enough to set up the google map and add the heat map to it. But it looks quite boring. I wanted to add somekind of a pulse effect to the heat map.
Thanks
It's straightforward to animate the heatmap's appearance. The following example sets a custom array of gradient colors and modulates its size. The result is sort of a pulsing effect. You may tweak the colors to your liking in the modulateGradient function or even add changes to the heatmap's opacity. Note, however, that depending on the size of your data set the animation might have a considerable performance impact.
HTML
<div id="map-canvas"></div>
JS
var map, pointarray, heatmap;
var gradient, gradientStep = -1;
var taxiData = [
new google.maps.LatLng(37.782551, -122.445368),
new google.maps.LatLng(37.782745, -122.444586),
new google.maps.LatLng(37.782842, -122.443688),
new google.maps.LatLng(37.782919, -122.442815),
new google.maps.LatLng(37.782992, -122.442112),
new google.maps.LatLng(37.783100, -122.441461),
new google.maps.LatLng(37.783206, -122.440829),
new google.maps.LatLng(37.783273, -122.440324),
new google.maps.LatLng(37.783316, -122.440023),
new google.maps.LatLng(37.783357, -122.439794),
new google.maps.LatLng(37.783371, -122.439687)
];
function initialize() {
var mapOptions = {
zoom: 13,
center: new google.maps.LatLng(37.774546, -122.433523),
mapTypeId: google.maps.MapTypeId.SATELLITE
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var pointArray = new google.maps.MVCArray(taxiData);
heatmap = new google.maps.visualization.HeatmapLayer({
data: pointArray
});
heatmap.setMap(map);
setGradient();
google.maps.event.addListenerOnce(map, 'tilesloaded', modulateGradient);
}
function setGradient() {
gradient = [
'rgba(0, 255, 255, 0)',
'rgba(0, 255, 255, 1)',
'rgba(0, 191, 255, 1)',
'rgba(0, 127, 255, 1)',
'rgba(0, 63, 255, 1)',
'rgba(0, 0, 255, 1)',
'rgba(0, 0, 223, 1)',
'rgba(0, 0, 191, 1)',
'rgba(0, 0, 159, 1)',
'rgba(0, 0, 127, 1)',
'rgba(63, 0, 91, 1)',
'rgba(127, 0, 63, 1)',
'rgba(191, 0, 31, 1)',
'rgba(255, 0, 0, 1)'
];
heatmap.set('gradient', gradient);
}
function modulateGradient() {
var modulator = function() {
var newGradient = gradient.slice(0, heatmap.get('gradient').length + gradientStep);
if (newGradient.length == gradient.length || newGradient.length == 7) {
gradientStep *= -1;
}
heatmap.set('gradient', newGradient);
setTimeout(modulator, 100);
};
setTimeout(modulator, 100);
}
google.maps.event.addDomListener(window, 'load', initialize);
You can find a live version of the code on JSFiddle.
You can create a kind of pulsing effect by changing the radius size of the heat map layer.
First let's make a var smallRadius and var bigRadius and set values to them; e.g. smallRadius = 40; bigRadius = 80;
then add the radius size to your var mapOptions and set it to smallRadius.
Then create an animateRadius() function which changes the radius value from smallRadius to bigRadius if it is set to smallRadius, else set the radius to smallRadius.
Then set the function to run every second or so by surrounding the function in a setInterval().
So Basically this:
var smallRadius = 40;
var bigRadius = 80;
var mapOptions = {
zoom: 13,
center: new google.maps.LatLng(37.774546, -122.433523),
mapTypeId: google.maps.MapTypeId.SATELLITE,
radius: smallRadius
};
//animate radius function
setInterval(function animateRadius()
{
if (heatMap.get('radius') === smallRadius)
{
heatMap.set('radius', bigRadius);
}
else
{
heatMap.set('radius', smallRadius);
}
}, 1000); // changes radius every 1 second
Obviously you can change the smallRadius and bigRadius to whatever values you want.
Related
var circleIdVal = UniqueKey();
String cir = circleIdVal.toString();
final CircleId circleId = CircleId(cir);
final Circle circle = Circle(circleId: circleId);
setState(() {
circles = Set.from([
Circle(
circleId: CircleId(cir),
center: LatLng(n1, n2),
radius: n3,
fillColor: Color.fromRGBO(255, 255, 255, .5),
strokeColor: Color.fromRGBO(247, 16, 0, .4))
]);
This is for a GoogleMap Widget. It plots fine but the old circle is constantly deleted and replaced with a new one.
additional info:
This is how it's called in the widget:
circles: circles,
and how it is set:
Set<Circle> circles;
Figured it out...
setState(() {
for (var i = 0; i < "test".length; i++) {
var circleIdVal = UniqueKey();
final CircleId circleId = CircleId(circleIdVal.toString());
final Circle circle = Circle(
circleId: circleId,
center: LatLng(
n1,
n2,),
radius: n3,
fillColor: Color.fromRGBO(255, 255, 255, .5),
strokeColor: Color.fromRGBO(247, 16, 0, .4));
setState(() {
circles[circleId] = circle;
});
}
});
}
I have attached my code below which I have been using to try and generate a clickable heatmap. The actual heatmap is generated but I cannot produce a click event.
Here is my code:
const centerLocation = new google.maps.LatLng(
Number(28.555040),
Number(77.241920)
);
const mapProp = {
center: centerLocation,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP,
clickableIcons: true
};
this.map = new google.maps.Map(this.gmapElement.nativeElement, mapProp);
const location = new google.maps.LatLng(
Number(28.555040),
Number(77.241920)
);
for (let i = 0; i < userData.length; i++) {
this.marker = new google.maps.Marker({
position: new google.maps.LatLng(+userData[i][1], +userData[i][2]),
map: this.map,
icon: this.userimage,
title: userData[i][0]
});
// tslint:disable-next-line:no-shadowed-variable
google.maps.event.addListener(this.marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent('' + userData[i][0] + '');
infowindow.open(this.map, this);
};
})(this.marker, i));
}
const infowindow = new google.maps.InfoWindow();
for (let i = 0; i < eventData.length; i++) {
this.marker = new google.maps.Marker({
position: new google.maps.LatLng(+eventData[i][1], +eventData[i][2]),
map: this.map,
icon: this.image,
title: eventData[i][0]
});
// tslint:disable-next-line:no-shadowed-variable
google.maps.event.addListener(this.marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent('' + eventData[i][0] + '');
infowindow.open(this.map, this);
};
})(this.marker, i));
}
// console.warn(location);
this.marker.setPosition(location);
this.heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
dissipating: true,
radius: 50
});
this.heatmap.setMap(this.map);
// For heatmap color
const gradient = [
'rgba(0, 255, 255, 0)',
'rgba(0, 255, 255, 1)',
'rgba(0, 191, 255, 1)',
'rgba(0, 127, 255, 1)',
'rgba(0, 63, 255, 1)',
'rgba(0, 0, 255, 1)',
'rgba(0, 0, 223, 1)',
'rgba(0, 0, 191, 1)',
'rgba(0, 0, 159, 1)',
'rgba(0, 0, 127, 1)',
'rgba(63, 0, 91, 1)',
'rgba(127, 0, 63, 1)',
'rgba(191, 0, 31, 1)',
'rgba(255, 0, 0, 1)'
];
this.heatmap.set('gradient', gradient);
// For heatmap color
this.heatmap.set('opacity', 0.6);
If by 'clickable' you mean interactive you may want to look at complexheatmaps which offer that specific utility. The supporting documentation can be found here. An example of what level of interactivity is possible can be found on this page.
Use one of the following to download the package...
Most Recent (you must use force = TRUE):
library(devtools)
install_github("jokergoo/ComplexHeatmap", force = TRUE)
library(ComplexHeatmap)
Stable:
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("ComplexHeatmap", version = "3.8")
Alternatively, you may want to look at using iheatmapr, though I know very little about it. As it is designed with interactivity as a forethough it may be of use to you. Here is how it was described in the Journal of Open Source Software.
There are great tools in R for creating simple interactive heatmaps
(Galili 2016, Cheng and Galili (2016)) or creating static complex
heatmaps (Gu, Eils, and Schlesner 2016). However, there are no tools
facilitating the creation of complex, interactive heatmaps.
Theiheatmapr package fills this gap, enabling the creation of highly
customizable, interactive, complex heatmaps using the plot library
(Sievert et al. 2016). The resulting interactive visualizations can
easily be incorporated into reproducible R Markdown reports for sharing
with collaborators
I want to draw some geometry in the map using canvas.getContext('2d'). However, the geometry I've drawn just show for a while. It disappear when I pan/zoom the map. How can I draw a permanent geometry through this way?
Below is my code:
<html>
<head>
<title></title>
<!-- styles -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.css"/>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
var map;
function init()
{
var raster = new ol.layer.Tile({
title:'basemap',
source: new ol.source.Stamen({
layer: 'toner'
})
});
map = new ol.Map( {layers:[raster],target:'map', view: new ol.View({
center: [113,25],
projection: 'EPSG:4326',
zoom: 6
})} );
};
function drawSth(){
var canvas = $("canvas")[0];
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
}
</script>
</head>
<body onload="init()">
<div id="map"></div>
<div id="controls">
<button onclick="drawSth();">just draw sth</button></br></br>
</div>
</body>
You can do that with an ol.source.ImageCanvas and its canvasFunction.
jsFiddle: https://jsfiddle.net/45oxL7rf/
var map = new ol.Map({
layers: [
new ol.layer.Tile({
title: 'basemap',
source: new ol.source.Stamen({ layer: 'toner' })
}),
new ol.layer.Image({
source: new ol.source.ImageCanvas({
canvasFunction: function (extent, resolution, pixelRatio, size, projection) {
var canvas = document.createElement('canvas');
canvas.width = size[0];
canvas.height = size[1];
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
return canvas;
},
projection: 'EPSG:3857'
})
})
],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([-97, 38]),
zoom: 4
})
});
Note that I just copy/pasted your canvas drawing and left it as is. As you pan the map, your graphic will not be anchored to the map as you might expect, since you're drawing to static pixel coordinates. In your real app, you'll likely be calculating the proper pixel coordinates based on the arguments passed into your canvasFunction.
I need to plot a specific values in a different locations ,these values i represents it as weights and send it with latlng coordinates . I need to know how Google calculate the color to modify my results ,such as i specify a color to each value or know how can i make google choose the desired color for my value?. can any one help me , please ?
var gradient3 = [
'rgba(0, 255, 255, 0)',
'rgba(0, 255, 255, 1)',
'rgba(0, 191, 255, 1)',
'rgba(0, 127, 255, 1)',
'rgba(0, 63, 255, 1)',
'rgba(0, 0, 255, 1)',
'rgba(0, 0, 223, 1)',
'rgba(0, 0, 191, 1)',
'rgba(0, 0, 159, 1)',
'rgba(0, 0, 127, 1)',
'rgba(63, 0, 91, 1)',
'rgba(127, 0, 63, 1)',
'rgba(191, 0, 31, 1)',
'rgba(255, 0, 0, 1)'
]
function initialize() {
//set some map options
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(37.774546, -122.433523),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//get a reference to the map area
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
patdata = [];
for (var i = 0; i < locationList.length; i++) {
var args = locationList[i].split(",");
patdata.push({
location: new google.maps.LatLng(args[0], args[1]),
weight: args[2]
});
}
heatmap = new google.maps.visualization.HeatmapLayer({
data: patdata
});
heatmap.setOptions({
//apply the gradient
gradient: heatmap.get('gradient') ? null : gradient3,
// set other options
maxIntensity: 25, //The maximum intensity of the heatmap
opacity: 0.8, //The opacity of the heatmap
radius: 8, //The radius of influence for each data point, in pixels.
//dissipating: true //Specifies whether heatmaps dissipate on zoom
});
heatmap.setMap(map);
I'm trying out smoothies charts
This is the json output from my server:
{"time": "1332216212", "in": "4.52", "out": "4.85"}
Here is the code that renders the chart:
<script type="text/javascript">
var dataSet1 = new TimeSeries(), dataSet2 = new TimeSeries();
setInterval(function() {
$.getJSON("/stats",function(data){
var now = new Date().getTime();
dataSet1.append(data.time, data.in);
dataSet2.append(data.time, data.out);
});
}, 1000);
var smoothie = new SmoothieChart({ minValue: 0.0, maxValue: 1.0, millisPerPixel: 20, grid: { strokeStyle: '#555555', lineWidth: 1, millisPerLine: 1000, verticalSections: 4 }});
smoothie.addTimeSeries(dataSet1, { strokeStyle: 'rgba(255, 0, 0, 1)', fillStyle: 'rgba(255, 0, 0, 0.2)', lineWidth: 3 });
smoothie.addTimeSeries(dataSet2, { strokeStyle: 'rgba(0, 255, 0, 1)', fillStyle: 'rgba(0, 255, 0, 0.2)', lineWidth: 3 });
smoothie.addTimeSeries(dataSet3, { strokeStyle: 'rgba(0, 0, 255, 1)', fillStyle: 'rgba(0, 0, 255, 0.2)', lineWidth: 3 });
smoothie.streamTo(document.getElementById('chart'), 1000);
</script>
Json data bandwidth stats. With the above code the graph doesn't get rendered. But the data gets fetched from the server according to web server logs. I'm using jquery1.3.2. Have I got anything wrong?
Try replacing 'data.time' in the append() function for each dataSet with your 'var now' you created. From my usage with Smoothie, it really wants the client-side (browser) to deal with the time for the graphing, rather than a value coming in off a server. If you need time information from an external source, then I'd suggest looking into Flot, because that will provide you with more functionality. Smoothie is very basic; it just wants data to plot on a real-time timeline.