I'm in need of a little assistance. I have a stacked area chart in d3.js using ordinal for the x axis (and likely for the y as well but haven't implemented that yet) and while it's rendering, it's not quite right. I need to figure out how to shift the chart (not the axis) so that the left most border is lined up vertically with the first tickmark and the rightmost is even with the last tickmark.
I've tried several variations and can't seem to figure out the starting x value.
Any help would be appreciated.
My x code
var x = d3.scale.ordinal().rangeRoundBands([0, width]);
x.domain(['Dec','Jan','Feb']); // Hard coded for now
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
A js fiddle of the entire chart (with data):
http://jsfiddle.net/adeaver/FRNbq/6/
Have you tried:
var x = d3.scale.ordinal()
.rangePoints([0, width]);
That may be what you are looking for.
This also works:
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 1, 0);
Related
I'm trying to plot some annotations to go along with my step function graphs. I currently have these graphs, and I've been trying to figure out how to draw horizontal arrows that point towards vertical lines. I will also need labeled, vertical lines that are pointing towards horizontal lines.
I have attached an image that shows (in red) what I mean. I've tried the annotation() function, but it's truly a pain to get the arrows where I want them to be. If anyone wouldn't mind explaining how to use that function, or alternative methods for what I'm trying to achieve, that would be amazing!
EDIT: Is there a way to edit the Quiver arrowhead size?
Using Quiver in a 2D Subplot
Not quite sure if this is any better or simpler but I used the quiver() function to plot the lines shown below. The quiver() function takes in a few inputs in this case. In the full script below I used twice the amount of quiver() calls to plot overlapping arrows to create a double headed arrow.
Function Call:
quiver(Start_Point(1),Start_Point(2),X_Displacement,Y_Displacement,0);
• Start_Point → equal to [x y] (x-coordinate y-coordinate)
• Start_Point(1) → The x-coordinate of the arrow's start
• Start_Point(2) → The y-coordinate of the arrow's start
• X_Displacement → The horizontal distance from the start of the array
• Y_Displacement → The vertical distance from the start of the array
Setting the Maximum Size of the Arrow Head:
The maximum size of the arrow head can be set by using the 'MaxHeadSize' property.
clf;
Start_Point(1) = 0;
Start_Point(2) = 0;
X_Displacement = 0; Y_Displacement = 10;
Magnitude = sqrt(X_Displacement.^2 + Y_Displacement.^2);
quiver(Start_Point(1),Start_Point(2),X_Displacement,Y_Displacement,0,'Color','r','MaxHeadSize',1/Magnitude);
hold on
Start_Point(1) = 0;
Start_Point(2) = 0;
X_Displacement = 100; Y_Displacement = 0;
Magnitude = sqrt(X_Displacement.^2 + Y_Displacement.^2);
quiver(Start_Point(1),Start_Point(2),X_Displacement,Y_Displacement,0,'Color','r','MaxHeadSize',1/Magnitude);
My d3 scatter plot uses historic date data in a range from 1600 to present. I can plot my dots successfully but can't display the dates prior to 1900 I the x axis.
I am using this example to make a scatterplot in d3 but my data has historic dates prior to 1900. I have tried to implement this solution but this returns a single date repeated for each tick mark
If I try to implement d3.axisBottom(x) this returns the dates from my data, but dates prior to 1900 are not formatted correctly.
I have made a plunker with full code
Here is my relevant scale and axis code (from the plunkr):
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x).ticks(10).tickFormat(function(d){return timeFormat(d);});
var yAxis = d3.axisLeft(y).ticks(10);
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) {return (d.dates);}))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
//.call(xAxis, function (d){return (d);});
//.call(xAxis, function (d){return (d.dates);}); // returns just a single date for all tick marks
.call(d3.axisBottom(x)); // partially correct dates but not formatting dates prior to 1900
My scatter plot is fine and the dots are as expected. What I want to see on the x axis is the dates prior to 1900, eg 1750.
Very grateful for help.
The referenced answer is correct, you have other issues in your code. I've also updated that answer a bit to clean the code and include a generic example with an axis from 1600-2000.
The first problem is that you define your x scale:
var x = d3.scaleTime().range([0, width]);
Then pretty much immediately define your axis:
var xAxis = d3.axisBottom(x)
.tickFormat(timeFormat);
Then you define the x domain, while redefining x as well with:
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) {return (d.dates);}))
.range([ 0, width ]);
If we use svg.call(xAxis), this means that the axis is using the first x scales domain, which defaults to [January 1 2000, January 2 2000], which is why every tick will have the same year if you apply the axis with only a default domain.
Your code has .call(d3.axisBottom(x) rather than .call(xAxis), which creates a new axis again, but without the formatting needed to render pre 1900 dates
Instead, determine the scale's domain first, then create the axis:
var x = d3.scaleTime()
.range([0, width])
.domain(d3.extent(data, function(d) {return (d.dates);}))
var xAxis = d3.axisBottom(x)
.tickFormat(timeFormat);
And now you can just apply the axis:
selection
.attr("transform",...)
.call(xAxis);
Here's an updated plunkr
Anybody know why the following is not reciprocal? latLng and new
var point = dispmap.latLngToContainerPoint(latlng);
var newPoint = L.point([point.x, point.y]);
var newLatLng = dispmap.containerPointToLatLng(newPoint);
When I execute this code I send in latlng=(26.75529,-80.93581)
newLatLng, which by inspection of the code above I would expect to reciprocate gives back...
newLatLng = (26.75542,-80.93628)
I'm wanting to array some markers with identical lat-lons around the shared spot on a map, and bumping each by some screen coordinates looks like the best method based on some blog/issue reading I've done.
I'm, "close" to what I want to achieve, but as I try to validate what these leaflet calls are doing for me I hit the fundamental question above.
They can't be ...
Latitude and longitude are float values while x and y are integer values.
This means that there are an (theoretically) infinite number of latlng's and a rather small number of points on your view (width * height).
Furthermore, I'm not sure how you define identical latlng's; the best you can't to is to speak of proximity.
If I read between the lines, identical may mean that the markers overlap. Then the best way is to have a look how Leaflet.MarkerCluster are tackling with the problem.
I was able to achieve my desired result by altering zoom level to avoid pixel-point quantization effects on my translations. The screenshot below illustrates an orange and two green circle markers that represent an identical lat-lon, but I want the green arrayed around the orange in a circular fashion...in this example there are only 2 green.
I perform simple circular array math with an angular step size of PI/4 in this example. The KEY to getting the visual effect correct is the "dispmap.setZoom(dispmap._layersMaxZoom)" call BEFORE I do the math, and then I invoke "dispmap.setZoom(mats.zoom)" after the math, which will give the user the desired zoom level as specified by variable mats.zoom.
var arrayRad=20;
var dtheta=Math.PI/4;
var theta=0;
dispmap.setZoom(dispmap._layersMaxZoom)
L.geoJson(JSON.parse(mats.intendeds), {
pointToLayer: function (feature, latlng) {
var point = dispmap.latLngToContainerPoint(latlng);
dx = arrayRad*Math.cos(theta);
dy = arrayRad*Math.sin(theta);
theta += dtheta;
var newPoint = L.point([point.x + dx, point.y+ dy]);
var newLatLng = dispmap.containerPointToLatLng(newPoint);
return L.circleMarker(newLatLng, intendedDeliveryLocationMarkerOptions);
}, onEachFeature: onEachIntendedLocFeature }).addTo(dispmap);
dispmap.setZoom(mats.zoom);
Sample screen shot at max zoom level: 2 arrayed markers
I generate a transparent chart that lets the background of a web page be seen through it.
So far I've done this (omited the populating of dataset for brevity):
lineChartObject=ChartFactory.createLineChart("Title","Legend","Amount",line_chart_dataset,PlotOrientation.VERTICAL,true,true,false);
CategoryPlot p = lineChartObject.getCategoryPlot();
Color trans = new Color(0xFF, 0xFF, 0xFF, 0);
lineChartObject.setBackgroundPaint(trans);
p.setBackgroundPaint(trans);
for (int i=0;i<=3;i++){
lineChartObject.getCategoryPlot().getRenderer().setSeriesStroke(i, new BasicStroke(3.0f));
lineChartObject.getCategoryPlot().getRenderer().setBaseItemLabelsVisible(false);
}
Which renders this:
I cannot find a way of:
Removing border of plot (1)
Removing border of leyend as well as making it transparent (3)
Making the labels on the X axis (2) to behave intelligently as the labels of Y axis do (A). Labels of Y axis space themselves so as to not clutter the graph, for example if I rendered the graph smaller, it would show fewer labels, like this:
Edit: X label domain is dates.
For (1) try:
plot.setOutlineVisible(false);
For (2), a common reason for having too many categories along the x-axis is that the data is actually numerical, in which case you should be using XYPlot rather than CategoryPlot. With XYPlot, the x-axis scale adjusts in the same way that the y-axis does.
Edit from OP: Using a TimeSeriesChart with a TimeSeriesCollection as XYDataSet did the work! (fotgot to say X domain is dates)
For (3) try:
LegendTitle legend = chart.getLegend();
legend.setFrame(BlockBorder.NONE);
legend.setBackgroundPaint(new Color(0, 0, 0, 0));
I'm trying to add a second Y axis to a StockChart with the Moxieapps Highcharts wrapper, but without success. I need to add a new axis on the right side of the chart, and would expect the following code to work:
StockChart chart = new StockChart();
YAxis firstYAxis = chart.getYAxis(0);
firstYAxis.setAxisTitleText("First Y axis");
Series firstSeries = chart.createSeries();
firstSeries.setPoints(/* Imagine lots of points. */);
firstSeries.setYAxis(0); // Not required since 0 is the default Y axis.
chart.addSeries(firstSeries);
YAxis secondYAxis = chart.getYAxis(1);
secondAxis.setOpposite(true); // *Should* put the axis on the right side.
secondYAxis.setAxisTitleText("Second Y axis");
Series secondSeries = chart.createSeries();
secondSeries.setPoints(/* Imagine lots of points. */);
secondSeries.setYAxis(1); // *Should* add the series to the second Y axis.
chart.addSeries(secondSeries);
// Somehow the second series ends up being in the navigator...
chart.setOption("navigator/enabled", true);
chart.setOption("scrollbar/enabled", true);
add(chart);
The second Y axis does not even render. If I don't add the second series to the second Y axis, it shows up (as expected) as values on the first Y axis.
Has anyone successfully added multiple Y axes on a StockChart, that can tell me what I'm doing wrong here? Thanks a lot in advance!
I had the same problem and it seems that GWT-HighCharts is the problem. You must create YAxises manually via native calls. Here is the solution;
HighCharts Stock Chart error code 18