问题
I have DB relation that holds information that I wish to display. each record holds a numerical value, and a 'name' that looks like '20140325_064532'.
The order of creating the records doesn't matter, and so I wish to present the numerical value on the y-axis and the x axis to have:
- to have constant margin between ticks.
- to present the data based on 'name' order (lexicographic).
- the x-axis label shouldn't present all the values, but "selected ones", such that no overlapping should be displayed.
- to prevent two point to be placed in the same x-value, even if they hold the same 'name' (the inner order has no meaning).
how should I define my Flot chart so this can be achieved?
EDIT: My implementation thoughts so far:
- I will fetch (distinctly) from the DB the 'name' field along with a row_number value (starting from 1).
- Based on that I'll create a Hash, using the names as the key to the row number. Lets say
:name => row#
I'll generate the series(s) with the following structure:
rawdata = [ [row#1, numericValue1], [row#2, numericValue2], ....];
Note that row# will be a numerical value starting at 1.
I'll define the ticks to represent the actual names. (This will be a line graph with dots, and not a bar chart).
Now, all of this will work (I think) but looks really messy. And, ontop, the ticks will almost surely overlap, and as to the fact that it will be hard coded, any zooming-in and out will not render the ticks with overlapping thoughts.
Update #2:
I passed the data to the js using two data attributes.
the 'results' has an array that representing the series, and holds 4 fields, such that
data-results="[[[0,371144,"20140206_000030-std",375],[1,373141,"20140328_230027",343],[2,374196,"20140401_230051",436],[3,374734,"20140401_230051_2",460],[4,374394,"20140401_230051_3",484],[5,376029,"20140401_230051_4",508]],... ,[another_series]]]
The 3rd field is 'name' and the last one is 'id'
the 'series' reresents the name I have for each series (and how it is displayed in the legend), and looks like:
data-series="["PLATFORM_A__CONFIG_B","PLATFORM_B__CONFIG_NONE"]"
I tried editing the content
of the tooltip trying to integrate information from the last part of each point, so that I'll have something like this displayed:
Run:
ID:
value: $y (the 2nd array field, representing the y-axis value)
I searched the web but couldn't find anything that works using tooltip (which looks nicer to handle). in the docs it is mentioned:
If you require even more control over how the tooltip is generated you can pass a callback function(label, xval, yval, flotItem) that must return a string with the format described.
I tried implementing this by calling Chart.getTooltip but all I get in the console is
Uncaught TypeError: undefined is not a function jquery.flot.tooltip.min.js?body=1:2h jquery.flot.tooltip.min.js?body=1:2(anonymous function) jquery.flot.tooltip.min.js?body=1:2jQuery.event.dispatch jquery.js?body=1:4642elemData.handle jquery.js?body=1:4310jQuery.event.trigger jquery.js?body=1:4551(anonymous function) jquery.js?body=1:5261jQuery.extend.each jquery.js?body=1:384jQuery.fn.jQuery.each jquery.js?body=1:137jQuery.fn.extend.trigger jquery.js?body=1:5260Y jquery.flot.cust.min.js?body=1:2V jquery.flot.cust.min.js?body=1:2jQuery.event.dispatch jquery.js?body=1:4642elemData.handle jquery.js?body=1:4310
Update #3
Thanks to @Ryley great tips and guidance, I was able to correctly display my chart using the unique values passed into Flot.
I've updated my code so that in order to avoid overlapping in the ticks values, I used flot-tickrotor
js to rotate the looks.
I've came across with a problem, in which my bottom values gets cut-off.
I've also noticed that this is a reported issue, but I couldn't find any solution or workaround for this.
Is there any solution for this issue?
Next, I want to enable to viewer to show/hide the series with a click. I found bunch of solutions, both official and others, but none of those worked for me. I'll explain:
- Official turning series on/off: this works, but looks very messy as the legend is eventually duplicated twice (disappears from official legend once the series turned off).
- Hiddengraphs.js: this is a plugin which can be found at the plugin repository, but it doesn't work and interact well with Chrome (tried more than one machine, it just don't work).
- This solution is actually really nice (I don't mind that there are no checkboxes to check), but when I integrated it into my code, all I got was "jumping" to the top of the page, and nothing happens.
- Lastly, I found this solution, which also works, altough using another js library, called
flot.togglelegend.js
. In this implementation I found some major conflicts withflot.cust.js
, and couldn't get them both to work together.
Finally, I tried to implement the select-zooming and double-click zoom-reset, using flot.selection.js
I was able indeed to get the functionality to work, but the re-rendering process generates into my second and third chart the data of the first one.
It is also worth saying that I'm rendering 3 charts in this page, all rendered in the same way.
Here's my updated code:
Here's my current js (written in coffeescript)
colorArray = []
colorArray.push "rgba(180, 0, 75, 0.6)"
colorArray.push "rgba(0, 150, 100, 0.6)"
colorArray.push "rgba(0, 0, 255, 0.6)"
colorArray.push "rgba(140, 0, 255, 0.6)"
colorArray.push "rgba(90, 180, 20, 0.6)"
colorArray.push "rgba(255, 236, 0, 0.6)"
colorArray.push "rgba(234, 170, 21, 0.6)"
colorArray.push "rgba(95, 180, 190, 0.6)"
colorArray.push "rgba(214, 92, 63, 0.6)"
colorArray.push "rgba(218, 106, 234, 0.6)"
colorArray.push "rgba(213, 128, 155, 0.6)"
# chart colors default
$chrt_border_color = "#efefef"
$chrt_grid_color = "#DDD"
$chrt_main = "#E24913"
# red
$chrt_second = "#6595b4"
# blue
$chrt_third = "#FF9F01"
# orange
$chrt_fourth = "#7e9d3a"
# green
$chrt_fifth = "#BD362F"
# dark red
$chrt_mono = "#000"
Chart =
generateDataObjects: (all_series, all_series_data) ->
plotData = []
for series, i in all_series
obj =
label: series.replace /__/g, "|"
data: all_series_data[i]
color: colorArray[i]
plotData.push obj
return plotData
getTooltip: (label, xval, yval, flotItem) ->
return 'Build: <span>'+ flotItem.series.data[flotItem.dataIndex][2]+'</span>' +" | Run ID: <strong> #{flotItem.series.data[flotItem.dataIndex][3].toString()}</strong>" + '<br> Result: <span>'+Chart.commify(yval)+'</span>'
commify: (x) ->
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
generateChartOptions: (legend_container, ticks) ->
return (
series:
lines:
show: true
points:
show: true
crosshair:
mode: "x"
legend:
container: $("##{legend_container}")
# labelFormatter: (label, series) ->
# "<a href=\"#\" onClick=\"togglePlot(" + series.idx + "); return false;\">" + label + "</a>"
noColumns: 4
# hideable: true
grid:
hoverable: true
clickable: true
tickColor: $chrt_border_color
borderWidth: 0
borderColor: $chrt_border_color
tooltip: true
tooltipOpts:
content : Chart.getTooltip
#content : "Value <b>$x</b> Value <span>$y</span>",
defaultTheme: false
xaxis:
ticks: ticks
rotateTicks: 30
selection:
mode: "xy"
)
jQuery -> if $("#normalized_bw_chart").length # render only if the chart-id is present
raw_data = $("#normalized_bw_chart").data('results')
ticks = $("#normalized_bw_chart").data('ticks')
all_series = $("#normalized_bw_chart").data('series')
plot = $.plot($("#normalized_bw_chart"), Chart.generateDataObjects(all_series, raw_data), Chart.generateChartOptions('normalized_bw_legend', ticks))
if $("#concurrent_flows_chart").length # render only if the chart-id is present
raw_data = $("#concurrent_flows_chart").data('results')
ticks = $("#concurrent_flows_chart").data('ticks')
all_series = $("#concurrent_flows_chart").data('series')
plot = $.plot($("#concurrent_flows_chart"), Chart.generateDataObjects(all_series, raw_data), Chart.generateChartOptions('concurrent_flows_legend', ticks))
if $("#bandwidth_chart").length # render only if the chart-id is present
raw_data = $("#bandwidth_chart").data('results')
ticks = $("#bandwidth_chart").data('ticks')
all_series = $("#bandwidth_chart").data('series')
plot = $.plot($("#bandwidth_chart"), Chart.generateDataObjects(all_series, raw_data), Chart.generateChartOptions('bandwidth_legend', ticks))
$("[data-behavior~=chart-selection]").bind "plotselected", (event, ranges) ->
selected_chart = $(this).attr('id')[0...-6] # slicing the name of the selected item
console.log ("zooming in to " + selected_chart)
plot = $.plot($("##{selected_chart}_chart"), plot.getData(), $.extend(true, {}, Chart.generateChartOptions(selected_chart+'_legend', ticks),
xaxis:
min: ranges.xaxis.from
max: ranges.xaxis.to
yaxis:
min: ranges.yaxis.from
max: ranges.yaxis.to
))
return
$("[data-behavior~=chart-selection]").bind "dblclick", (event, pos, item) ->
selected_chart = $(this).attr('id')[0...-6] # slicing the name of the selected item
console.log ("zooming out to " + selected_chart)
plot = $.plot($("##{selected_chart}_chart"), plot.getData(), $.extend(true, {}, Chart.generateChartOptions(selected_chart+'_legend', ticks),
xaxis:
min: null
max: null
yaxis:
min: null
max: null
))
return
thanks a lot!
回答1:
Well, you got most of the way there, I just finished it off for you...
Basic issues:
Data format is
[[x1,y1],[x2,y2],...
data: [[all_series_data[i][0],all_series_data[i][1]]]
Specify ticks correctly (this just grabs every odd one)
tick_labels = [] for series, i in all_series if i % 2 tick_labels.push [i,series] else tick_labels.push [i,'']
and then in your plot options:
xaxis:
ticks: tick_labels
- include the tooltip library and use it in the default way. I used a copy from a CDN.
- fix a basic coffeescript syntax error (probably just from copying it over here). In your
GenerateChartOptions
you open a(
and never close it at the end.
Here's a working example: http://jsfiddle.net/ryleyb/0tn1uzs9/2/
Based on comments I added this to the example:
#in the flot options
tooltipOpts:
content: Chart.getToolTip
#to the Chart object
getToolTip: (label, xval, yval, flotItem) ->
return 'Run: '+raw_data[xval][3]+': value: '+Chart.commify(yval)
commify: (x) ->
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
来源:https://stackoverflow.com/questions/25870691/flot-charts-producing-custom-trend-with-unique-x-axis-values