When I hover on the lines on the cumulative line chart I get a tooltip message x value at some y time. I want to edit this message and add more content.
Since in my values array I have json containing {X:x, Y:y, Z:z, Dt:date} I wish to show a custom message listing X/Y/Z at date.
I'm using nvd3 veraion 1.1.15b.
Calling .tooltip() didn't work for me, but calling .tooltipContent() did, as in the following code:
var chart = nv.models.pieChart()
.x(function (d) { return d.file; })
.y(function (d) { return d.size; })
.tooltipContent(function (key, y, e, graph) {
return '<h3>' + key + '</h3>' +
'<p>' + e.value.toSizeFmt() + '</p>';
})
As Andrei points out above, the e parameter provides access to the raw values so you can format them, rather than working with y which is already formatted text. Hope this helps!
If you have not found a proper solution yet, here you try this -
nv.addGraph(function() {
var chart = nv.models.cumulativeLineChart().x(function(d) {
return d[0]
}).y(function(d) {
return d[1]
}).color(d3.scale.category10().range()).tooltip(function(key, x, y, e, graph) {
return '<h3>' + key + ' Custom Text Here ' + x + '</h3> here' + '<p> or here ,' + y + '</p>'
});
});
Hope it helps.
Related
I'm trying to plot a dc choropleth , but somehow the legend is not showing up.
Here is the sample fiddle :
http://jsfiddle.net/susram/9VJHe/56/
usChart
.width(1200)
.height(500)
.dimension(state_dim)
.group(latest_mean_sqft_per_state)
//.colors(d3.scale.quantize().range(["#E2F2FF", "#C4E4FF", "#9ED2FF", "#81C5FF", "#6BBAFF", "#51AEFF", "#36A2FF", "#1E96FF", "#0089FF", "#0061B5"]))
.colors(d3.scale.quantize().range(["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"]))
//.colors(d3.scale.quantize().range(d3.schemeBlues()(9)))
.colorDomain([0, 500])
//.colorAccessor(function (d) { /*console.log(d);*/ return d? usChart.colors(d.avg_psft) : '#ccc'; })
.colorAccessor(function (d) { /*console.log(d);*/ return d.avg_psft; })
.overlayGeoJson(statesJson.features, "state", function (d) {
return d.properties.name;
})
.valueAccessor(function(kv) {
console.log(kv);
return kv.value;
})
.title(function (d) {
return "State: " + d.key + "\nAverage Price per SqFt: " + numberFormat(d.value.avg_psft ? d.value.avg_psft : 0) + "M";
})
.legend(dc.legend().x(1300).y(80).itemHeight(13).gap(5));
Why is the legend showing up as 0x0 ?
I've been trying to get the legend to work with geoChoroplethCharts as well and unfortunately legend support appears to not have been implemented yet in dc. There are a few functions (legendables, legendHighlight, legendReset, legendToggle, ect...) that were defined in the dc base-mixin and would need to be extended before legend support would work.
For an example take a look at the source for pieChart:
https://github.com/dc-js/dc.js/blob/develop/src/pie-chart.js
Versus the soruce for geoChoroplethChart:
https://github.com/dc-js/dc.js/blob/develop/src/geo-choropleth-chart.js
You'll notice at the bottom of the pieChart source that the related legend functions were extended. I belive something similar would need to be done for the geoChoroplethChart source code.
EDIT:
I worked off your jsfiddle and was able to get a bare bones label to display on the geoChoroplethChart: http://jsfiddle.net/Lx3x929v/2/
usChart.legendables = function () {
return usChart.group().all().map(function (d, i) {
var legendable = {name: d.key, data: d.value, others: d.others,
chart: usChart};
legendable.color = usChart.colorCalculator()(d.value);
return legendable;
});
};
Here is my modification —for a continuous map— from #MarcTifrea 's solution and comment.
chart.legendables = function () {
var domain = chart.colorDomain();
return domain.map(function (d, i) {
var legendable = {name: parseFloat((Math.round(domain[i] * 100000) /100000).toPrecision(2)) , chart: chart};
if (i==1) legendable.name += ' unit'; // add the unit only in second(last) legend item
legendable.color = chart.colorCalculator()(domain[i]);
return legendable;
});
};
chart.legend(
dc.legend()
.x(width/4)
.y(height*4/5)
.itemHeight(height/30)
// .itemWidth(width/25)
.gap(5)
// .horizontal(1)
// .autoItemWidth(1)
);
I am trying to draw two choropleths ( US states and county) in a page, using dc.js . The us county map is somehow becoming invisible. The dom elements are present, properly with path and fill values, when inspected (as shown in the figure). I'm able to click on those inivisible counties and able to affect the filters as expected. The fill colors are accurate as per the cross_filtered data. Why is the color fill not happening properly ? What is it missing here ?
d3.json(load_geojson_states){
<code for states json>
d3.json(load_geojson_county){
<define dimensions>
<define group on dimension>
usChart_cnt
.width(1000)
.height(500)
.dimension(cnt_dim)
.group(change_p_sqft_cnt_group)
.colors(d3.scale.quantize().range(["#E2F2FF", "#C4E4FF", "#9ED2FF", "#81C5FF", "#6BBAFF", "#51AEFF", "#36A2FF", "#1E96FF", "#0089FF", "#0061B5"]))
.colorDomain([0, 30])
.colorAccessor(function (d) { /*console.log(d);*/ return d? d.chng_pct:0; })
.overlayGeoJson(countyJson.features, "county", function (d) { return d.properties.FIPS; })
.valueAccessor(function(kv) { //console.log(kv);
return kv.value;
})
.title(function (d) {
return "County: " + d.key + "\nChange in Price per SqFt: " + numberFormat(d.value ? d.value.chng_pct : 0) + "%";
})
dc.renderAll();
}
}
This issue is resolved by referring to this post: DC.js choropleth map chart CSS conflicting with colouring, no map showing. How can I turn off the fill:none?
The whole issue is because the 'county' class gets over-rided with css from dc.js . Upon changing the class name as follows ,i'm seeing the values getting filled up properly :
.overlayGeoJson(countyJson.features, "cnty", function (d) { return d.properties.FIPS; })
I am using d3-dagre to render the data. Initially i can render the data without any problem. When i try to update the same view in watch mode, it is updating the data but still some error is thrown in the console for "g" attribute transformation. Whenever i try to rewrite the SVG elements i am removing the "g" element inside the "svg" tag. I am trying this in vuejs2 ui library.
watch: {
workflowDetails: function (changes) {
console.log('Update component ==> ' + changes)
this.workflowName = changes.label
this.workflowDetails = changes
this.metricGraph = false
this.drawDAGView()
}
},
mounted () {
this.drawDAGView()
},
methods: {
getJobid: function (nodeId) {
console.log('Function to get graph api' + nodeId)
this.metricGraph = true
},
drawDAGView: function (isUpdate) {
/* eslint-disable */
d3.selectAll('svg > g').remove()
// Create a new directed graph
var g = new dagreD3.graphlib.Graph().setGraph({})
var DagNodes = this.workflowDetails.nodes
var fillColor
// Add states to the graph, set labels, and style
Object.keys(DagNodes).forEach(function(key) {
console.log("Nodes - "+ DagNodes[key].name)
var value = DagNodes[key]
value.label = DagNodes[key].name + " (" + DagNodes[key].exec_time + ")"
value.rx = value.ry = 5
g.setNode(DagNodes[key].name, value)
})
var DagEdges = this.workflowDetails.edges;
// Add states to the graph, set labels, and style
Object.keys(DagEdges).forEach(function(key) {
g.setEdge(DagEdges[key].startEdge, DagEdges[key].endEdge, { label: ""} )
})
// Create the renderer
var render = new dagreD3.render()
// Set up an SVG group so that we can translate the final graph.
var svg = d3.select("svg"),
inner = svg.append("g")
// Set up zoom support
var zoom = d3.behavior.zoom().on("zoom", function() {
inner.attr("transform", "translate(" + d3.event.translate + ")" +
"scale(" + d3.event.scale + ")")
})
svg.call(zoom)
// Simple function to style the tooltip for the given node.
var styleTooltip = function(name, description) {
return "<p class='name'>" + name + "</p><p class='description'>" + description + "</p>"
}
// Run the renderer. This is what draws the final graph.
render(inner, g)
inner.selectAll("g.node")
.attr("title", function(v) {
return styleTooltip(v, "Execution Time: "+g.node(v).label + " <br /> Description: "+g.node(v).label)
})
//.each(function(v) { $(this).tipsy({ gravity: "w", opacity: 1, html: true }) })
var self = this
inner.selectAll("g.node")
.on("click", function(v) {
console.log("Nodes --> "+ v + " -- "+ g.node(v).node_id)
// whatever
//window.location = "../dag/"+g.node(v).job_id
self.nodeId = g.node(v).node_id
console.log("Node id -- "+ self.nodeId)
self.getJobid(self.nodeId)
})
// Center the graph
var initialScale = 1.2
zoom
.translate([(svg.attr("width") - g.graph().width * initialScale) / 50, 20])
.scale(initialScale)
.event(svg)
svg.attr('height', g.graph().height * initialScale + 40)
svg.attr('width', "100%")
}
Error - Due to this below error newly loaded data not able to zoom
Error: <g> attribute transform: Expected number, "translate(NaN,20)
Have you tried removing the svg? After removing the svg you can add the new Graph.
I have a C3 xy chart, that I'm trying to add an onclick to. The onclick is commented out (lines 58-70) in the attached fiddle. Scatter Fiddle The chart does not show when I have the onclick code included, somewhere I've messed up the syntax.
var clickEvent = function(d) {
var clickData = d.id;
var clickValue = d.value; //y value ROS
var clickCat = [d.x]; //x value AU
var clickLegend = [d.name];
var clickYear = d.id == 'data1' ? tooltips.data1[d.index] : d.id == 'data2' ? tooltips.data2[d.index] : d.id == 'data3' ? tooltips.data3[d.index] : d.id == 'data4' ? tooltips.data4[d.index] : null;
var allTogether = clickData + "|" + clickValue + "|" + clickCat + "|" + clickLegend + "|" + clickYear;
var theURL = alert(allTogether);
}
onclick: clickEvent
After extracting your method declaration outside of your config I could see that you messed up your configuration. After your comment
//type: 'scatter' // uncoment to remove lines
were some closing brackets which closed your data property. So you actually placed your onclick function outside this property which is equivalent of no method being declared.
Here is your fixed fiddle.
.legend(dc.legend().x(0).y(5).itemHeight(5).gap(8).horizontal(1)
.legendWidth(90).itemWidth(95).legendText(function (d) {
if (d.name == 'category4') {
return ' VI>20 ' + " " + " : " + d.data;
}
if (d.name == 'category3') {
return 'VI>10 and <=20 ' + " " + " : " + d.data;
}
if (d.name == 'category2') {
return 'VI>5 and <=10 ' + " " + " : " + d.data;
}
if (d.name == 'category1') {
return 'VI<=5 ' + " " + " : " + d.data;
};
}));
I want to display d.data in different color and proper alignment.
I think by proper alignment, you mean right-alignment of the numbers.
In general, dc.js can't anticipate every formatting option anyone would want, so most of the accessors and formatters just generate text. But you can customize it by hooking into events.
Your tools here are the pretransition event handler, and tspans within the text elements created for the legend.
For example, to split the name and data and left-align the name but right-align the data a bit to the right, you could do:
chart.on('pretransition', function(chart) {
chart.selectAll('.dc-legend-item text')
.text('')
.append('tspan')
.text(function(d) { return d.name; })
.append('tspan')
.attr('x', 100)
.attr('text-anchor', 'end')
.text(function(d) { return d.data; });
});
You'll just need to adjust the processing of the category names.
I've added this to the pie external labels example.