Am new to angularjs/googlecharts and learning on the job. I've the following code in my controller which renders the piechart initially and has no issues.
There is a slider directive, which when changed (basically a date range slider), should update the columnchart with new data. But I don't know how to update the piechart data. I do get the new data from the backend without any problems though.
Here is the initialization code in controller:
$scope.piechart = {};
$scope.piechart.type ='PieChart';
piechartData = response.data.piechart;
var piechartoptions = {
'min-width':800,
'max-width':320,
'is3D':true,
'pieSliceText': 'label',
'pieSliceTextStyle': {fontSize: 10},
'chartArea' : { left: 30, top: 60 },
'backgroundColor': {fill:'transparent'},
'legend': {'textStyle':{'color': 'white',
'fontSize': 12},
'position': "top",
'maxLines':10,
'alignment':"start"},
'height':500
};
$scope.piechart.data = new google.visualization.DataTable(piechartData);
$scope.piechart.options = piechartoptions;
$scope.piechart.formatters = {};
In the directive (which is used in the html that the above controller's scope resides in), I've access to the chart like the following:
scope.$parent.piechart
So in a very naive way i did this but to no avail:
scope.$parent.piechart.data = new google.visualization.DataTable(response.data.piechart)
TIA for all the help.
I bumped into this issue today. An easy quick fix is to simply write
this.chartData = Object.assign([], this.chartData) to reassign to the exposed dataset property into your component so it triggers change detection.
More information from this issue in a different library:
valor-software/ng2-charts#959 (comment)
Hope this helps weary travellers :)
To achieve this you need to create watch on your slider model so when it gets change you need to update your pie chart model so it'll automatically update.
Watch
$scope.$watch('sliderModel',function(n,o) {
// update your new pie chart data here, I think you need to update below model only
$scope.piechart.data = new google.visualization.DataTable(piechartData);
}
It just an example. You have to update it with new data for pie chart.
Proper Angular way to use google chart
You should use google-chart directives to plot pie chart so this kind of problems will be solved automatically.
Have a look here - Angular-google-chart
Related
My application shows a map with react-leaflet and uses LayersControl to switch between an OSM TileLayer and HERE TileLayer. The code is as follows:
<LayersControl position="topright">
<LayersControl.BaseLayer
name={this.props.intl.formatMessage({id:'map.normal_map'})}
checked={true}
>
{ tileLayerOSM }
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name={this.props.intl.formatMessage({id:'map.terrain_map'})}>
{ tileLayerHERE }
</LayersControl.BaseLayer>
</LayersControl>
The problema I see is the following: when moving the OSM map, some 'squares' are downloaded from HERE while they are not ready with OSM. See the network trace:
I would like to avoid this behavior, since it is a bit annoying for the user, who see changes in the visualization for a short period of time.
I don't have experience using Leaflet with React, but these is clearly not the desired behaviour.
In Leaflet that (retrive the both base layers at the same time) happens when you add both to the map. Something like:
const accessToken = 'foo';
let osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
const mapbox = 'https://api.mapbox.com/styles/v1/mapbox/basic-9/tiles/256/{z}/{x}/{y}?access_token={accessToken}';
const map = L.map('map').setView([42.2, -8.8], 12);
map.addLayer(osm);
map.addLayer(mapbox); // only one should be added to the map
or directly when instantiating the map:
let map = L.map('map', {
center: [42.2, -8.8],
zoom: 12,
layers: [osm, mapbox] // only one should be added to the map
});
With this kind of baselayers you only must add one to the map and use the layer control to switch between one or the other. When only one is added only the tiles for one of the maps are requested, saving bandwith.
As a "shot in the dark" I will try to make the checked value explicit for all layers. First both as a harcoded false, nothing should be shown in the map. Then one with checked=true harcoded and the other with false, and so on. Probably the trouble is how those attributes are managed.
For my client, i have created a drawing using a 3d approach. here is the live :
http://plnkr.co/edit/8fDkcEwpCsx0bi1f467b?p=preview
and the code i used is :
$(document).ready( function () {
var salesData=[
{label:"Basic", color:"#e9d600"},
{label:"Plus", color:"#DC3912"},
{label:"Lite", color:"#1fc2c7"}
];
var svg = d3.select("body").append("svg").attr("width",700).attr("height",300);
svg.append("g").attr("id","salesDonut");
Donut3D.draw("salesDonut", randomData(), 350, 150, 130, 100, 50, 0.4);
function randomData(){
return salesData.map(function(d){
return {label:d.label, value:1000*Math.random(), color:d.color};});
};
})
it works fine. But my client asking to make a graph like this :
how to create like this? What is this chart type call as? I don't have any idea to make this.
any one expertised with d3js, can you please help me to reproducing the basic level or showing a tutorial or giving me a guide?
thanks in advance.
Background
I have an angular-meteor app and a collection of business objects in mongodb, e.g.:
{ startDate: new Date(2015, 1, 1), duration: 65, value: 36 }
I want to render this data in different views. One of the views is a graph, another is a list of entries.
The list of entries is easy. Just bind the collection to the model:
vm.entries = $scope.meteorCollection(MyData, false);
In the view I would do:
<div ng-repeat="entry in vm.entries">{{entry.startDate}} - ...</div>
But now for the graph. I want to transform each element into a { x, y } object and give the view that, e.g.:
vm.graphPoints = transformData(getDataHere());
The problem is that the data is not fetched here, in angular-meteor is looks like it is fetched when calling the entry in vm.entries in the view. The kicker is that the transformData method, needs to loop through the data and for each item index into other items to calculate the resulting x, y. Hence I cannot use a simple forEach loop (without having access to the other items in some way).
Question
So how can i fetch the data in the controller - transform it - and still have one-way binding (observing) on new data added to the database?
Thanks
Update
The following code works, but I think there could be performance problems with fetching the whole collection each time there is a change.
$scope.$meteorSubscribe("myData").then(function() {
$scope.$meteorAutorun(function() {
var rawData = MyData.find().fetch();
vm.model.myData = transformData(rawData);
});
});
EDIT:
This is the current solution:
$scope.collectionData = $scope.meteorCollection(MyData, false);
$meteor.autorun($scope, function() {
vm.graphPoints = transformData($scope.collectionData.fetch());
});
There is some missing information. do you wan't to have some kind of model object in the client? if that is correct I think you have to do something like this:
$meteor.autorun($scope, function() {
vm.graphPoints = transformData($scope.meteorCollection(MyData, false));
});
How about using the Collection Helper Meteor package to add the function:
https://github.com/dburles/meteor-collection-helpers/
?
I'm trying to find a map solution that is possible to highlight and click on various regions, one region would be Africa. I'm also looking for a solution that will work well with Angularjs.
I thought the Google Visualization Chart might be suitable. This allows the selection of regions using the region codes listed on the site.
I've tried adding a few regions, the only one I could get working was Australia (AU), the following don't work for me:
['Europe', 150],
['Western Asia', 145],
['Asia', 142],
['Africa', 002]
Here's the jsfiddle I'm using to test this.
Am I doing something wrong or is there an issue with the chart itself?
Thank you.
google.setOnLoadCallback(drawRegionsMap);
function drawRegionsMap() {
var data = google.visualization.arrayToDataTable([
['Region Code', 'Continent', 'Popularity'],
['142', 'Asia', 200],
['150', 'Europe', 300],
['019', 'Americas', 400],
['009', 'Oceania', 600],
['002', 'Africa', 700]
]);
var options = {
resolution: 'continents'
};
var chart = new google.visualization.GeoChart(document.getElementById('regions_div'));
chart.draw(data, options);
}
This jsfiddle shows how to do it:
I have a problem with WMS overlays in OpenLayers. Basically I just want to add data from a WMS server as an overlay and not as a base layer. This appears to be a very simple problem but I am unable to find a solution. If I set singleTile to true, the overlays appears over the whole map but you cannot zoom in. If it is set to false, only one tile is displayed at every zoom level. If I set it as a base layer, it works just fine but I really want the overlay solution so I can make it transparent and see the map behind it.
Demonstration of the problem, with a different dataset but the issue is the same:
http://jsfiddle.net/adbnC/2/
I think it might be related to some coordinate system issues but I am no expert so any help is appreciated.
Thanks a lot!
Here is the relevant section of the code that does not work as expected:
var pop_layer = new OpenLayers.Layer.WMS("Population Density in 2000",
"http://sedac.ciesin.columbia.edu/geoserver/ows", {
layers: 'gpw-v3:gpw-v3-population-density_2000',
transparent: true
}, {
opacity: 0.5,
isBaseLayer: false,
// Setting single tile to true will kind of work but than one
// cannot zoom in any more.
singleTile: false
}
);
I can't quite get what exactly is wrong here, but I think it has something to do with messed up reference systems. Here is a workaround:
Modified Jsfiddle.net
I changed the map projection to spherical mercator and now it seems to work fine for me:
var mapOptions = {
div: "map",
projection: new OpenLayers.Projection("EPSG:900913"),
units: "m"
};
map = new OpenLayers.Map('map', mapOptions);
var osm = new OpenLayers.Layer.OSM();
map.addLayer(osm);
var pop_layer = new OpenLayers.Layer.WMS("Population Density in 2000", "http://sedac.ciesin.columbia.edu/geoserver/ows", {
layers: 'gpw-v3:gpw-v3-population-density_2000',
transparent: true
}, {
opacity: 0.5,
isBaseLayer: false
});
map.addLayer(osm);
map.addLayer(pop_layer);
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.setCenter(new OpenLayers.LonLat(0, 0), 2);
Let me know if that helped!