Show only top 5 values in legend for Pie Chart (Am4 charts) - legend

I have a pie chart with legends made using Am4 charts but I need to display only the top 5 legend values. I wrote the following code:
var chart = am4core.create("chartdiv2", am4charts.PieChart);
chart.hiddenState.properties.opacity = 0; // this creates initial fade-in
// Add data
chart.data = [{
"country": "Lithuania",
"litres": 501.9
}, {
"country": "Czech Republic",
"litres": 301.9
}, {
"country": "Ireland",
"litres": 201.1
}, {
"country": "Germany",
"litres": 165.8
}, {
"country": "Belgium",
"litres": 60
}, {
"country": "The Netherlands",
"litres": 50
}];
// Set inner radius
chart.innerRadius = am4core.percent(50);
//Add label
var label = chart.seriesContainer.createChild(am4core.Label);
label.text = "200";
label.horizontalCenter = "middle";
label.verticalCenter = "middle";
// label.fontSize = 50;
// Add and configure Series
var pieSeries = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template.strokeWidth = 2;
pieSeries.slices.template.strokeOpacity = 1;
pieSeries.ticks.template.disabled = true;
pieSeries.labels.template.disabled = true;
// This creates initial animation
pieSeries.hiddenState.properties.opacity = 1;
pieSeries.hiddenState.properties.endAngle = -90;
pieSeries.hiddenState.properties.startAngle = -90;
pieSeries.legendSettings.labelText = '{category}';
pieSeries.legendSettings.valueText = null;
pieSeries.labels.template.text = "{category}: {value}";
pieSeries.slices.template.tooltipText = "{category}: {value}";
chart.legend = new am4charts.Legend();
chart.legend.fontSize = 10;
chart.legend.markers.template.width = 10;
chart.legend.markers.template.height = 10;
I need only Lithuania, Czech Republic, Ireland, Germany and Belgium to show up in the legend but currently, they all show up. In the pic, I have highlighted the legend values that should not show up.
I tried using the legend.data array but it always returns an empty array.
How do I go about solving this?

Related

Add second Y axis on Plotly.kt

For all the different plotly languages version there is an option to generate graphs with two Y axis.
Either with the use of secondary_y or yaxis2 depending on the language.
I have browsed the different examples on the Plotly.kt github but haven't found a way to do this.
Is this even possible with the Kotlin version of Plotly ?
I have tried adding two yaxis blocks, but the second one just seems to overwrite the first one.
val plot = Plotly.plot {
traces(
scatter {
x.strings = priceData.map { it.first.toString() }
y.numbers = priceData.map { it.second }
mode = ScatterMode.lines
axis("Price")
},
bar {
x.strings = volumeData.map { it.first.toString() }
y.numbers = volumeData.map { it.second }
marker {
width = 1.0
opacity = 0.4
}
axis("Volume")
}
)
layout {
title { text = "Sales"}
showlegend = false
xaxis {
type = AxisType.date
gridwidth = 2.0
}
yaxis {
type = AxisType.linear
automargin = true
gridwidth = 2.0
title = "Price"
}
yaxis {
type = AxisType.linear
showgrid = false
title = "Volume"
}
}
}

Vertical legend in pieChart in one column in nvd3

I need vertical legend in PieChart.
Now library provide only 2 options: top/right.
If use right - legend is in several columns. I need legend in one column.
I found one hack - correct transform value and put legend in one column.
var positionX = 30;
var positionY = 30;
var verticalOffset = 25;
d3.selectAll('.nv-legend .nv-series')[0].forEach(function(d) {
positionY += verticalOffset;
d3.select(d).attr('transform', 'translate(' + positionX + ',' + positionY + ')');
});
It works, but If I click to legend to update it - legend return to start position (several columns).
JSFiddle example
A workaround for this is to update the legend for every click and double click of .nv-legend.
(function() {
var h = 600;
var r = h / 2;
var arc = d3.svg.arc().outerRadius(r);
var data = [{
"label": "Test 1",
"value": 74
}, {
"label": "Test 2",
"value": 7
}, {
"label": "Test 3",
"value": 7
}, {
"label": "Test 4",
"value": 12
}];
var colors = [
'rgb(178, 55, 56)',
'rgb(213, 69, 70)',
'rgb(230, 125, 126)',
'rgb(239, 183, 182)'
]
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) {
return d.label
})
.y(function(d) {
return d.value
})
.color(colors)
.showLabels(true)
.labelType("percent");
d3.select("#chart svg")
.datum(data)
.transition().duration(1200)
.call(chart);
var svg = d3.select("#chart svg");
function updateLegendPosition() {
svg.selectAll(".nv-series")[0].forEach(function(d, i) {
d3.select(d).attr("transform", "translate(0," + i * 15 + ")");
})
}
svg.select('.nv-legend').on("click", function() {
updateLegendPosition();
});
svg.select('.nv-legend').on("dblclick", function() {
updateLegendPosition();
});
updateLegendPosition();
return chart;
});
}())
#import url(http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans+Mono);
#chart svg {
height: 600px;
}
.nv-label text{
font-family: Droid Sans;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.js"></script>
<div id="chart">
<svg></svg>
</div>
A Quick Hack.
Modify the nv.d3.js
Line 11149 (May differ on other versions )
// Legend
if (showLegend) {
if (legendPosition === "top") {
Add another option vertical
} else if (legendPosition === "vertical") {
var legendWidth = nv.models.legend().width();
var positionY = 10;
var positionX = availableWidth - 200;
var verticalOffset = 20;
if ( margin.top != legend.height()) {
margin.top = legend.height();
availableHeight = nv.utils.availableHeight(height, container, margin);
}
legend.width(200);
// legend.height(availableHeight).key(pie.x());
positionY += verticalOffset;
wrap.select('.nv-legendWrap')
.datum(data)
.call(legend)
.attr('transform', 'translate(' + positionX + ',' + positionY + ')');
}
Also can play with variables.
Works very nice with Legends. For a very long list of legends. More logic want to apply.
I know this is an old question, but I had the same one and ended up here. None of the answers worked for me, but I was able to modfiy Ranijth's answer and get it working (and looking nice).
else if (legendPosition === "vertical") {
var pad=50;
var legendWidth=150; //might need to change this
legend.height(availableHeight).key(pie.x());
legend.width(legendWidth);
wrap.select('.nv-legendWrap')
.datum(data)
.call(legend)
.attr('transform', 'translate('+ ((availableWidth / 2)+legendWidth+pad)+','+pad+')');
}
Pie Chart with Vertical Legend

Hide ArcGis Markers

We are trying to find suggestions, or implementation options on how to hide a marker once a new point on the map has been clicked.
In our application, once the user clicks on a particular pin on the map, we display a new pin (in a different lat/long location) that is associated with the click event. I.e. a point should be in oklahoma, but the map is displaying texas, so once the marker texas is clicked, a new marker in oklahoma is shown. Our issue is that whenever a user selects a new point, we are not able to "hide" the marker for the previous selection, which then clutters our screen.
Any suggestions on how we could handle this issue?
Code is below:
require(["esri/map", "esri/geometry/Point", "esri/symbols/SimpleMarkerSymbol", "esri/graphic", "dojo/_base/array", "dojo/dom-style", "dojox/widget/ColorPicker", "esri/InfoTemplate", "esri/Color", "dojo/dom", "dojo/domReady!", "esri/geometry/Polyline", "esri/geometry/geodesicUtils", "esri/units","esri/symbols/SimpleLineSymbol"],
function( Map, Point,SimpleMarkerSymbol, Graphic, arrayUtils, domStyle, ColorPicker, InfoTemplate, Color, dom, Polyline, geodesicUtils, Units,SimpleLineSymbol) {
map = new Map("mapDiv", {
center : [-98.35, 35.50],
zoom : 5,
basemap : "topo"
//basemap types: "streets", "satellite", "hybrid", "topo", "gray", "oceans", "osm", "national-geographic"
} );
map.on("load", pinMap);
var arr = [];
var initColor, iconPath;
function pinMap( ) {
map.graphics.clear();
iconPath = "M16,3.5c-4.142,0-7.5,3.358-7.5,7.5c0,4.143,7.5,18.121,7.5,18.121S23.5,15.143,23.5,11C23.5,6.858,20.143,3.5,16,3.5z M16,14.584c-1.979,0-3.584-1.604-3.584-3.584S14.021,7.416,16,7.416S19.584,9.021,19.584,11S17.979,14.584,16,14.584z";
var infoContent = "<b>Id</b>: ${Id} ";
var infoTemplate = new InfoTemplate(" Details",infoContent);
$.post( '{{ path( 'points' ) }}', {}, function( r ) {
arrayUtils.forEach( r.points, function( point ) {
if (point.test==1) {
initColor = "#CF3A3A";
}
else {
initColor = "#FF9900";
}
arr.push(point.id,point.pinLon1,point.pinLat1,point.pinLon2,point.pinLat2);
var attributes = {"Site URL":point.url,"Activity Id":point.id,"Updated By":point.updated,"Customer":point.customer};
var graphic = new Graphic(new Point(point.pinLon1,point.pinLat1),createSymbol(iconPath,initColor),attributes,infoTemplate);
map.graphics.add( graphic );
map.graphics.on("click",function(evt){
var Content = evt.graphic.getContent();
var storeId = getStoreId(Content);
sitePins(storeId);
});
} );
}, 'json' );
}
function getStoreId( content ){
var init = content.split(":");
var fin= init[2].split("<");
return fin[0].trim();
}
function sitePins( siteId ) {
iconPathSite = "M15.834,29.084 15.834,16.166 2.917,16.166 29.083,2.917z";
initColorSite = "#005CE6";
var infoContent = "<b>Distance</b>: ${Distance} Miles";
var infoTemplate = new InfoTemplate(" Distance to Location",infoContent);
var indexValue=0;
for (var index = 0; index < arr.length; index++){
if (arr[index]==storeId){
indexValue =index;
}
}
pinLon1 = arr[indexValue+1];
pinLat1 = arr[indexValue+2];
pinLon2 = arr[indexValue+3];
pinLat2 = arr[indexValue+4];
var line = {"paths":[[[pinLon1, pinLat1], [pinLon2, pinLat2]]]};
line = new esri.geometry.Polyline(line);
var lengths = Number(esri.geometry.geodesicLengths([line], esri.Units.MILES)).toFixed(2);
var attributes = {"Distance":lengths};
var graphicSite = new Graphic(new Point (pinLon1,pinLat1), createSymbol(iconPathSite, initColorSite),attributes,infoTemplate);
var pathLine = new esri.Graphic(line, new esri.symbol.SimpleLineSymbol());
map.graphics.add( pathLine );
map.graphics.add( graphicSite );
}
function createSymbol( path, color ) {
var markerSymbol = new esri.symbol.SimpleMarkerSymbol( );
markerSymbol.setPath(path);
markerSymbol.setSize(18);
markerSymbol.setColor(new dojo.Color(color));
markerSymbol.setOutline(null);
return markerSymbol;
}
} );
</script>
As far as I get the code, it shows the distance between the marker and the point then clicked.You are creating point and polyline on each click event on map. Following can help:
1) Please provide id say 'abc' to polyline, graphic site.
2) Then on every click event remove the graphic and polyline with id 'abc'.
dojo.forEach(this.map.graphics.graphics, function(g) {
if( g && g.id === "abc" ) {
//remove graphic with specific id
this.map.graphics.remove(g);
}
}, this);
3) Then you can create the new polyline and point as you are already doing it.

How best to traverse API information with iOS

Is there any easier way of traversing array/dictionaries without creating a lot of separate NSArrays/NSDictionaries? I know you can traverse nested dictionaries with dot notation and value at keypath, but what about when arrays are involved?
For example:
At the moment if I want to get at the object at feed.entry.link[4].href in the API result below, I have to define an array at keypath "feed.entry", then assign its first entry as a dictionary, then define an array at keypath "link" and access its fourth entry as a dictionary, and then access its value at "href".
Is this normal?
received {
encoding = "UTF-8";
feed = {
entry = (
{
author = (
{
name = {
"$t" = swdestiny;
};
uri = {
"$t" = "https://gdata.youtube.com/feeds/api/users/swdestiny";
};
}
);
category = (
{
scheme = "http://schemas.google.com/g/2005#kind";
term = "http://gdata.youtube.com/schemas/2007#video";
},
{
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
term = Entertainment;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Star;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Wars;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Episode;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = 3;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Revenge;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = of;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = the;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Sith;
}
);
content = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = text;
};
"gd$comments" = {
"gd$feedLink" = {
countHint = 1567;
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/comments";
rel = "http://gdata.youtube.com/schemas/2007#comments";
};
};
"gd$rating" = {
average = "4.7729683";
max = 5;
min = 1;
numRaters = 1132;
rel = "http://schemas.google.com/g/2005#overall";
};
id = {
"$t" = "http://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
};
link = (
{
href = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata";
rel = alternate;
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/responses";
rel = "http://gdata.youtube.com/schemas/2007#video.responses";
type = "application/atom+xml";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/related";
rel = "http://gdata.youtube.com/schemas/2007#video.related";
type = "application/atom+xml";
},
{
href = "https://m.youtube.com/details?v=9kdEsZH5ohc";
rel = "http://gdata.youtube.com/schemas/2007#mobile";
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
rel = self;
type = "application/atom+xml";
}
);
"media$group" = {
"media$category" = (
{
"$t" = Entertainment;
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
}
);
"media$content" = (
{
duration = 151;
expression = full;
isDefault = true;
medium = video;
type = "application/x-shockwave-flash";
url = "https://www.youtube.com/v/9kdEsZH5ohc?version=3&f=videos&app=youtube_gdata";
"yt$format" = 5;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache4.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 1;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache5.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 6;
}
);
"media$description" = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = plain;
};
"media$keywords" = {
"$t" = "Star, Wars, Episode, 3, Revenge, of, the, Sith";
};
"media$player" = (
{
url = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata_player";
}
);
"media$thumbnail" = (
{
height = 360;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/0.jpg";
width = 480;
},
{
height = 90;
time = "00:00:37.750";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/1.jpg";
width = 120;
},
{
height = 90;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/2.jpg";
width = 120;
},
{
height = 90;
time = "00:01:53.250";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/3.jpg";
width = 120;
}
);
"media$title" = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = plain;
};
"yt$duration" = {
seconds = 151;
};
};
published = {
"$t" = "2007-05-23T03:31:54.000Z";
};
title = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = text;
};
updated = {
"$t" = "2012-02-20T17:14:37.000Z";
};
"yt$statistics" = {
favoriteCount = 763;
viewCount = 796719;
};
}
);
xmlns = "http://www.w3.org/2005/Atom";
"xmlns$gd" = "http://schemas.google.com/g/2005";
"xmlns$media" = "http://search.yahoo.com/mrss/";
"xmlns$yt" = "http://gdata.youtube.com/schemas/2007";
};
version = "1.0";
}

Creating dynamic labels for dojo bar chart

I have bar chart, whose x-axis labels is generated dynamically from db, I am getting these values through ajax call data
'{value:1,text:"x"},{value:2,text:"Vikash"},{value:3,text:"y"},{value:4,text:"z"}'.
How to pass these values to label parameter. I tried passing it as an array and also as json but nothing seems to work.. Any ideas..
Here is my code:
makeBarChart=function() {
animChart = new dojox.charting.Chart2D("animChart");
animChart.setTheme(dojox.charting.themes.MiamiNice)
.addAxis("x",{
labels: [ myLabelSeriesarray ], gap: 20}).
addAxis("y", {
vertical: true,
fixLower: "major",
fixUpper: "major",
includeZero: true
}).
addPlot("default", {
type: "ClusteredColumns",
gap: 10
}).
addSeries("Series A", closedSeries).
addSeries("Series B", othersSeries).
render();
};
dojo.addOnLoad(makeBarChart);
jsp code:
var labelDis = new Array(pieData.length); // pieData is the JSON value getting from Java
for(var i = 0;i<pieData.length;i++){
labelDis[i] = new Array(2);
labelDis[i]['value'] = i + 1;
labelDis[i]['text'] = pieData[i]['axis'];
}
Java/Servlet code:
JSONObject jSONObject = new JSONObject();
jSONObject.put("axis", "value from database");
jSONArray.put(jSONObject);
out.print(jSONArray.toString());
Suppose you have received data in json format through ajax call and you want to create dynamic labels using that data.
var jsonArray= ["label1","label2","label3"];
var labelsArray = [];
for (var i = 0; i < jsonArray.length; i++,) {
var obj = {};
obj.value = i;
obj.text = jsonArray[i];
labelsArray.push(obj);
}
Set the labels in x Axis to this labelsArray
this.chart1.addAxis("x", {
title: "Collection Date",
titleOrientation: "away",
titleGap:20,
labels:labelsArray
})