I'm trying to render the legend of a pie chart so that it has a fixed width, and when the labels reach that width (the div holder) to hyphenate on the next line. I tried the row option but it doesn't work very well because my data is dynamic and at times i have say 3 data sets, and each one of them gets rendered in a separate row, while at other times i have 15-20 data sets and it becomes messy.
Anyway the solution is to restrain the legend to the width of the div, that it is rendered into, yet it doesn't seem to be accepting any css alterations. I tried adding width:250px; to the "jqplot-table-legend" in jqPlot css, i also tried adding it into various places using Inspect Element in Chrome to test whether it works, but it doesn't seem to accept the new width. I also tried to hard code it into the javascript file at various places with no luck.
I'm not sure what I can add to the question in terms of code. Everything is pretty standard on the jqPlot side.
Any suggestions on how to get around this will be much appreciated.
This seems like the quick and dirty way, but it gets the job done. I'll use the jqplot.pieRenderer.js file as the example since it's easier to read than the minified version. Open the js file and scroll down to line 568. Right under
this._elem = $(document.createElement('table'));
this._elem.addClass('jqplot-table-legend');
add
this._elem.css({width: 300});
That will stretch the table out to whatever width you need it to be. Unfortunately, it also stretches out the column with the color swatch so you'll now need to scroll down a little further until you find
td1.css({textAlign: 'center', paddingTop: rs});
change that to
td1.css({width: 16, textAlign: 'center', paddingTop: rs});
and you should be all set.
Another method:
Just add these lines:
if (this.width) {
ss['width'] = this.width;
}
They allow you to set an arbitrary width in each different graph
You might also want to add these lines in jquery.jqplot.js (i.e if rendering bars)
Search for "createElement('table')" as described by mike
Worked for me
Related
I'm working on a timeline-based chart that should always have one rect per x-axis tick. The idea is to use the color of each rectangle to convey the amount of data that's in that date (somewhat like a heatmap).
The chart also has grouped y values. That is, there are two y axes: one for each group, and inside each of those, three lines (subgroups). Semantically the intention is to say: "For this coupon, on this date, there are this many readings for each data type". To help clear up my intention further, this library has a very similar solution to what I'm aiming at.
OK, and your question...?
My question is about aligning the rectangles with the ticks, and keeping them that way. How can I make them always be aligned with the ticks? Is there a way to "tie" a rect to a tick?
To make matters worst, the chart has to be zoomable, so when you scroll and the dimensions of the ticks change, the rectangles should stick to their corresponding ticks: move with them, change their width accordingly and so on. Basically, I'd like to "marry" the rects to their corresponding ticks.
What have you tried?
My approach right now is to make the segments' width depend on the current tick count, and essentially treat the current ticks as if they were my data.
That is:
segmentWidth = state.width() / ticks.length;
And when updating/rendering the rects:
state.mainG.selectAll('g.couponData')
.selectAll('g.column')
.data(ticks)
...
One problem I see with this is that if you click and drag, the ticks expand, so having a single, global segmentWidth doesn't seem like the right approach. Seems like I'd need a way to grab each tick and get the distance to the next one, and use that as the width of each corresponding segment, but I haven't quite got there yet.
Here's a fiddle with an example of what I have:
https://jsfiddle.net/bnekvp0o/11/
TBH, I presume I'm making some dumb calculation mistakes, but I also feel like I'm bruteforcing the solution, so I'm hesitant to keep trying to make it work with my current approach, since I'm quite new to the framework.
Thanks in advance!
I am trying to modify the cycling example from the react-timeseries-charts repository. I would like to add vertical lines that span across all rows (much like the cursor tracker does).
I have added the TimeMarker component to the charts array:
charts.push(
<LineChart
key={`line-${channelName}`}
axis={`${channelName}_axis`}
series={series}
columns={[channelName]}
style={style}
breakLine
interpolation={"curveStepAfter"}
/>
);
charts.push(
<TimeMarker
time={4500}
/>
);
This displays a vertical line on all plots as expected however the line doesn't span the full height of each ChartRow so visually looks disjointed (see image).
I have tried playing around with each of the props on TimeMarker but can't find any that alter the line height and can't find anything in the docs either.
Any help would be much appreciated.
Cheers,
P
edit: image upload doesn't seem to work, hopefully it's clear what I mean. There's about 10px of whitespace between each chart row where I would like the line to continue to produce a single joined up vertical line across all rows.
PROLOGUE
This is my first time posting to stackoverflow and i'm a noob with dc.js. Apologies in advance for etiquette transgressions (feedback welcome on this too)
PROBLEM
I have defined a barchart and it displays perfectly, but brushOn(true) is not letting me filter the data. In the past, this seemed to work perfectly with a crosshair appearing as soon as i hovered over the bargraph. Now it is not. Any idea why?! or what i can do to fix it? I'm on day 3 of trying to figure out what is happening. The help is MUCH appreciated!
PREREQS:
https://d3js.org/d3.v5.min.js
crossfilter.min.js
https://unpkg.com/dc#3.0.4/dc.js
CODE FOR BARCHART
I have defined a barchart as follows:
filterDim = cross.dimension(function(d){return d3.timeWeek(d.date);});
var filterGroup = filterDim.group().reduceSum(function(d){
if(d.isTrue){return 1;}
else {return 0;} });
height=400;
if(width == 0){
width = $(dom_id).parent().innerWidth();
}
var hitsbarChart = dc.barChart(dom_id);
hitsbarChart
.width(width).height(height)
.dimension(sentDimension)
.group(allGroups[0].data,allGroups[0].name)
.xUnits(d3.timeWeeks);
hitsbarChart
.x(d3.scaleTime())
.valueAccessor(function(d){return d.value;})
.keyAccessor(function(d){return d.key;})
.round(d3.timeWeek.round)
.yAxis().ticks(d3.format('.3s'));
function calc_domain(chart) {
var min = d3.min(chart.group().all(), function(kv) { return kv.key; }),
max = d3.max(chart.group().all(), function(kv) { return kv.key; });
max = d3.timeMonth.offset(max, 1);
chart.x().domain([min, max]);
}
hitsbarChart.on('preRender', calc_domain);
hitsbarChart.on('preRedraw', calc_domain);
hitsbarChart.brushOn(true);
dc.renderAll();
RESEARCH
I found this example which demonstrates something different but outputs a graph with time-series as the x-axis and working brush to select a range of dates.
Also, there this bug with work-around but the work around did not work. I can't imagine that time-series data works more like an ordinal scale than a numerical scale.
It's likely that you have some CSS inadvertently affecting your chart when it was supposed to be control some other part of the page.
This could happen either because you used a generic name which is also used by dc.js or d3.js, or because a style sheet from another library does. All of dc.js's style rules are carefully scoped so that they shouldn't affect anyone else, but many common words are used for class names, so interference the other way is common.
The brushing behavior comes from d3, so I'd try looking at d3's g.brush rect.overlay in the inspector of your developer tools. You should be able to bring it up by right-clicking the background of the chart and selecting Inspect.
If it has something like
pointer-events: none;
or
display: none;
applied to it, find out what applied that (hopefully CSS you control) and try to make the rules more specific.
Of course it's also possible for JavaScript from another library to cause such troubles, but interference from CSS is much more common.
I want to remove (or make effectively hidden) the first vertical line in the grid for an nvd3 chart. I thought it was a problem with my chart, but after testing it, I realized it seems to be a more general problem.
I tested it by running the line:
d3.selectAll('.tick, .nv-axislabel, .nv-axis text').attr('fill','#999999')
in the console, at the simplest line chart I could find: http://nvd3.org/examples/line.html and it still didn't work! It changes all the lines except the very first vertical line. I'm baffled, I've tried every combination of classes with stroke, fill, opacity, etc - I can either affect the entire svg (with opacity), or nothing. Anyone have any ideas?
EDIT:
I should have specified this originally, I apologize - I do not want to remove the Y axis entirely. I still need the label and the tick marks - I just want to remove that one vertical line (or at least lighten it - it is much darker than the rest of my chart).
Going by your comments:
You don't want to see the " the first vertical line in the grid for an nvd3 chart"
Which is the y axis:
Two ways to achieve that:
Option1
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(false) //hide the y-axis
.showXAxis(true); //Show the x-axis
Option2:
Since in your example you are going for a CSS option
d3.selectAll('.nv-y').attr('display','none')
I will prefer Option1
EDIT post your clarification, you wish to make the y axis line light you can use:
d3.selectAll('.nv-y path').attr('opacity','0.1')
or if you want to hide it completely
d3.selectAll('.nv-y path').attr('display','none')
One solution is to specify an array of tick values that you want to use for each axis. Use axis.tickValues([values]) to explicitly declare which XAxis ticks you want for your graph. So you could pop .tickValues([1, 2, 3, 5, 8, 13, 21]); into either the chart.xAxis or the chart.yAxis, and ticks would only appear from the corresponding values in the array. In your case, you would want to put it in the chart.xAxis variable. However if you want to have a dynamic chart, explicitly declaring the tick values would pose a problem once the data is updated in the graph. If on the other hand you are using static data, this is a pretty easy fix. I've tested this solution in their live code editor and it seems to do the trick.
Refer to https://github.com/mbostock/d3/wiki/SVG-Axes#ticks to see some other directives that could be of use.
http://d.pr/i/U5bb/4n26fLZr
Here's an example of a chart of ours. Pretty unreadable, yea? Is there an easy, dynamic way avoid this? I've tried implementing a dynamic height, but the problem is I can never seem to find the sweet spot that accommodates a smaller number of bars, and a larger number of bars. I feel like this has to be a problem that others have encountered before. Any help would be appreciated!
I accomplish this by doing the following:
1) determine height of non-data elements on the chart (ie, explicitly set the top and bottom margins, and add them together to get a base_height for the chart
2) determine how much space I want each bar to take, including bar width, and padding between bars, and set as my height_multiplier (I usually end up going for 20-25 pixels, personally)
3) on pulling my data, determine how many bars will be needed, and set as my bar_count
4) calculate: chart_height = base_height + (bar_count * height_multiplier)
5) Pass that value to the html to set the height of the chart's containing element.
If your data will vary so much that the chart height in your example works some times, but then you have as many data points as you've posted there, there simply will not be a 'sweet spot' that will handle both extremes well.