I'm using NVD3 to display of a number of line charts and would like to be able to get the min and max values of the xAxis currently displayed. In this case the xAxis shows time values.
When toggling the visibility of lines in the chart, by clicking the legend label, the date range is changed. I've added an event handler to listen to legendClicks but how do I get my hands on the newly rendered date range?
I ended up using a custom function to find the min/max values of the x axis when clicking the legend. I wrapped the function within a $timeout in order to wait for the digest cycle to be completed to get the proper value, ie:
legend: {
dispatch: {
legendClick: function(e) {
$timeout(function(){
getMinMax();
}, 0);
}
}
},
The getMinMax function is a quick and dirty one and may most likely be done in a more elegantly manner, however it does its job:
var getMinMax = function(){
var maxVal, minVal = null;
for(var i=0;i<$scope.data.length;i++) {
// Only displayed should be considered
if (!$scope.data[i].disabled) {
var tempMinVal = d3.max($scope.data[i].values, function(d) { return d.x;} );
var tempMaxVal = d3.min($scope.data[i].values, function(d) { return d.x;} );
minVal = (!minVal || tempMinVal < minVal) ? tempMinVal : minVal;
maxVal = (!maxVal || tempMaxVal > maxVal) ? tempMaxVal : maxVal;
}
}
return [minVal, maxVal];
};
Will get the min and max from the data in this format:
[
{
"key": "AA",
"values": [
{
"x": 1440712800000,
"y": "6",
"series": 0
},
{
"x": 1440712800000,
"y": "6",
"series": 0
}
]
},
{
"key": "BB",
"values": [
{
"x": 1441144800000,
"y": "3",
"series": 1
},
{
"x": 1443045600000,
"y": "3",
"series": 1
},
{
"x": 1453244400000,
"y": "3",
"series": 1
},
{
"x": 1454022000000,
"y": "3",
"series": 1
}
]
},
{
"key": "CC",
"values": [
{
"x": 1442872800000,
"y": "5",
"series": 2
},
{
"x": 1442872800000,
"y": "5",
"series": 2
}
]
},
{
"key": "DD",
"values": [
{
"x": 1443650400000,
"y": "1",
"series": 3
},
{
"x": 1443650400000,
"y": "1",
"series": 3
}
]
},
{
"key": "EE",
"values": [
{
"x": 1444773600000,
"y": "9",
"series": 4
},
{
"x": 1446073200000,
"y": "9",
"series": 4
}
]
}
]
As I reached this far the client changed mind and didn't want the functionality that required this solution. Hope it may be of use for someone else.
Related
I'm trying to show labels on a point FeatureLayer, the label is not visible for just one Feature, But it become visible when the map change scale, is there any explanation?
Here is my code:
"renderer": {
"type": "class-breaks",
"field": "nums",
"classBreakInfos": [
{
"minValue": 0,
"maxValue": 9,
"label": " < 10",
"symbol": {
"type": "picture-marker",
"url": "./assets/picto/nums/vert.png",
"width": 30,
"height": 50
}
},
{
"minValue": 10,
"maxValue": 19,
"label": " 10 à 19",
"symbol": {
"type": "picture-marker",
"url": "./assets/picto/nums/orange.png",
"width": 30,
"height": 50
}
},
{
"minValue": 20,
"maxValue": 1000000,
"label": " > 19",
"symbol": {
"type": "picture-marker",
"url": "./assets/picto/nums/rouge.png",
"width": 30,
"height": 50
}
}
]
},
"labelingInfo": [
{
"labelExpressionInfo": {
"expression": "$feature.nums"
},
"labelPlacement": "center-center",
"symbol": {
"type": "text",
"color": "black",
"haloColor": "white",
"xoffset": -2,
"yoffset": 13,
"font": {
"size": 7,
"family": "sans-serif",
"weight": "bolder"
}
}
}
]
I joined a picture of the FeatureLayer labels problem:
Base on you definition, you are using the default deconflict strategy ("static"). Sometimes when overlaps occurs the overlapped label is not showed. Depends on the situation this strategy make sense or not.
You could try "none" option, to turn off deconfliction and you should not have that issue. It seems it might be what you are looking for.
labelClass.deconflictionStrategy = "none";
ArcGIS JS API - LabelClass deconflictionStrategy
I have $balance that is returned from another function like this:
$balance = {
"data": [
{
"name": "ABS",
"y": 1450
},
{
"name": "PBT",
"y": 1200
},
{
"name": "Краситель",
"y": 1000
},
{
"name": "PP",
"y": 750
}
]
}
And I have also collection called $statistics like this:
$statistics = [
{
"name": "ABS",
"data": []
},
{
"name": "PP",
"data": []
},
{
"name": "PBT",
"data": []
},
{
"name": "Краситель",
"data": []
}
]
What I'm trying to do is pushing all y 's of $balance to corresponding $statistics by matching their name.
Here is short description of my code:
foreach ($balance["data"] as $firm){
$statistics->firstWhere('name', $firm->name)['data']->push($firm->y);
}
However, I'm getting Call to a member function push() on null error. Can anyone help me find out the problem
I am using a d3.js time.scale like this:
var xScale = d3.time.scale()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([0, chartWidth]);
The data is like this:
var testData = [
{
"date": "2015-04-01T00:00:00.000Z",
"value": 200.00
},
{
"date": "2015-05-01T00:00:00.000Z",
"value": 2000.00
},
{
"date": "2015-06-01T00:00:00.000Z",
"value": 4000.01
},
{
"date": "2015-07-01T00:00:00.000Z",
"value": 1000.00
},
{
"date": "2015-08-01T00:00:00.000Z",
"value": 750.00
},
{
"date": "2015-09-01T00:00:00.000Z",
"value": 1568.00
},
{
"date": "2015-10-01T00:00:00.000Z",
"value": 3789.00
},
{
"date": "2015-11-01T00:00:00.000Z",
"value": 5678.00
},
{
"date": "2015-12-01T00:00:00.000Z",
"value": 4898.00
},
{
"date": "2016-01-01T00:00:00.000Z",
"value": 9002.00
},
{
"date": "2016-02-01T00:00:00.000Z",
"value": 3320.00
},
{
"date": "2016-03-01T00:00:00.000Z",
"value": 12000.00
}
];
But the ticks and the ordering are not as I would expect:
I would expect the ticks to be ordered from april 2015 to march 2016 and I do not understand where the 2016 tick is coming from.
How can I order the ticks as I would expect and also where is the 2016 tick coming from?
Here is a jsbin that shows the problem
If you want the ticks to show the month name and the year, add this to the axis:
.tickFormat(d3.time.format("%B %Y"));
Alternatively, you can display the abbreviated month name:
.tickFormat(d3.time.format("%b %Y"));
Here is the updated jsbin: http://jsbin.com/wikafuluqu/1/edit?js,output
PS: To show the first tick, add nice() to the scale. This is the jsbin with nice():
http://jsbin.com/loyupelazu/1/edit?js,output
This is my document
{
"name": "andrew",
"b": [{"x":"c1", "y": 0}, {"x":"c2", "y": 0}]
}
I want to find element in the array field "b" and update the entire object. I tried this script but it does not update. Any ideas?
{
"script": "for (item in ctx._source.b) { if (item['x'] == x_id) { item = newobj; } };",
"params": {
"x_id": "c1",
"newobj" : {"x":"c1", "y": 4222}
},
"lang":"groovy"
}
Use this instead:
{
"script": "for (int i=0;i<ctx._source.b.size();i++) { item=ctx._source.b[i]; if (item['x'] == x_id) { ctx._source.b[i] = newobj} };",
"params": {
"x_id": "c1",
"newobj": {
"x": "c1",
"y": 4222
}
},
"lang": "groovy"
}
I am drawing a intractive graph using amcharts. I want to draw several line graphs in one single graph. But my code draw only one graph. When I add code for second line graph , it did not show anything due to error. How I can add second line graph in it. Here is .js file.
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"marginTop":0,
"marginRight": 80,
"dataProvider": [{
"D": "100",
"value": 10
}, {
"D": "200",
"value": 20
}, {
"D": "200",
"value": 30
}, {
"D": "400",
"value": 40
}, {
"D": "500",
"value": 50
}],
"graphs": [{
"id":"g1",
"balloonText": "[[category]]<br><b><span style='font-size:14px;'>[[value]]</span></b>",
"bullet": "round",
"bulletSize": 8,
"lineColor": "#d1655d",
"lineThickness": 2,
"negativeLineColor": "#637bb6",
"type": "smoothedLine",
"valueField": "value"
}],
"chartCursor": { /* required for zoom effect */
"cursorAlpha": 0,
"valueLineEnabled":true,
"valueLineBalloonEnabled":true,
"valueLineAlpha":0.5,
"fullWidth":true
},
/*show x axis values on graph*/
"categoryField": "D",
});
chart.addListener("rendered", zoomChart);
if(chart.zoomChart){
chart.zoomChart();
}
function zoomChart(){
chart.zoomToIndexes(Math.round(chart.dataProvider.length * 0.4), Math.round(chart.dataProvider.length * 0.55));
}
I found a solution. If you want to plot more linegraphs in one single graph. Just add extra id' in "graph": and add extra valueField inside that id. And add needed points in "dataProvider":. Similarly you can do this for more than 2 graphs by adding ids inside "graph":. And save it with .js extension.
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"marginTop":0,
"marginRight": 80,
"dataProvider": [{
"D": "5",
"value":0.30,
"value1":0.5,
}, {
"D": "10",
"value": 0.29,
"value1":0.27,
}, {
"D": "15",
"value": 0.28,
"value1":0.20,
}, {
"D": "20",
"value": 0.27,
"value1":0.32,
}, {
"D": "25",
"value": 0.26,
"value1":0.25,
}],
"graphs": [{
"id":"g1",
"balloonText": "[[category]]<br><b><span style='font-size:14px;'>[[value]]</span></b>",
"bullet": "round",
"bulletSize": 8,
"lineColor": "#d1655d",
"lineThickness": 2,
"negativeLineColor": "#637bb6",
"type": "smoothedLine",
"title": "redpoint",
"valueField": "value"
}, {
"id":"g2",
"balloonText": "[[category]]<br><b><span style='font-size:14px;> [value]]</span></b>",
"bullet": "round",
"bulletSize": 8,
"lineColor": "#20acd4",
"lineThickness": 2,
"negativeLineColor": "#637bb6",
"type": "smoothedLine",
"title": "bluepoint",
"valueField": "value1"
}],
"chartCursor": { /* required for zoom effect */
"cursorAlpha": 0,
"valueLineEnabled":true,
"valueLineBalloonEnabled":true,
"valueLineAlpha":0.5,
"fullWidth":true
},
/*legend show points value on top*/
"legend": {
"useGraphSettings": true,
"position": "top"
},
/*show x axis values on graph*/
"categoryField": "D",
});
chart.addListener("rendered", zoomChart);/*zoom effect*/
if(chart.zoomChart){
chart.zoomChart();
}
function zoomChart(){
chart.zoomToIndexes(Math.round(chart.dataProvider.length * 0.4), Math.round(chart.dataProvider.length * 0.55));
}