I want to add an image in nvd3 piechart legend instead of text.
I have this code but it changes only the text in the tooltip with the image. I want to change and the text in the legend with the same image.
var testdata = [
{
key: "<img src="+"./imgs/facebook.jpg"+">",
y: 1
},
{
key: ""<img src="+"./imgs/twitter.jpg"+">"",
y: 2
} ];
nv.addGraph(function() {
var chart = nv.models.pieChart()
.x(function(d) { return d.key})
.labelThreshold(.08)
.showLabels(true)
.color(d3.scale.category10().range())
.donut(true);
chart.pie.donutLabelsOutside(true).donut(true);
d3.select("#mypiechart")
.datum(testdata)
.transition().duration(1200)
.call(chart);
return chart;});
Any ideas?
This is not currently possible with nvd3.js. The tooltip works because the img element you have specified is being set into a div that isn't contained within the svg element. It doesn't work for the legend or chart labels because those are built using svg text elements. In order to show an image within the chart svg we'd need to use an svg image element.
We could build the svg image elements if we hack the nvd3.js code. Here's an outline of what you could do to get the legend working. You could then decide if you'd want to try something similar in the nv.models.pie code for the chart labels or if you'd just want to set chart.showLabels to false in your chart configuration.
Add a new key in your data to provide the image path:
var testdata = [
{
key: "<img src="+"./imgs/facebook.jpg"+">",
y: 1,
image_path: "./imgs/facebook.jpg"
},
{
key: "<img src="+"./imgs/twitter.jpg"+">",
y: 2,
image_path: "./imgs/twitter.jpg"
} ];
Update the nv.models.legend code to show the image:
seriesEnter.append('circle')
.style('stroke-width', 2)
.attr('class','nv-legend-symbol')
.attr('r', 5);
// Add an svg image into the legend
seriesEnter.append('image')
.attr('xlink:href', function(d) { return d.image_path} )
.attr('height',20)
.attr('width',20)
.attr('y', '-10')
.attr('x', '8');
Update the nv.models.legend code to not show the key:
// Don't add the key value into the legend text
//series.select('text').text(getKey);
Update the nv.models.legend code to consider the image width when determining the legend layout:
//seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding
//Include image width...
seriesWidths.push(nodeTextLength + 48);
Related
Is there a way to put legend outside the chart area? I'm trying with bindto property, but it doesn't work (plunker)
Here is the example for amcharts
In C3 documentation there are only few positions allowed: top-left
top-right bottom-left bottom-right
You could always just re-parent it yourself:
setTimeout(function(){
var legend = d3.selectAll('.c3-legend-item');
var svg = d3.select('#legend')
.append('svg')
.attr('width', 640)
.attr('height', 100);
legend.each(function(){
svg.node().appendChild(this);
});
}, 100);
Updated plunker.
You can probably solve this using:
legend: {
show: false
}
And then adding a custom legend via C3 or D3
See http://c3js.org/samples/legend_custom.html for a working example
I am trying to add radio buttons to an area with axis and shapes like this:
var triangleFunctions = ['Perpendicular Bisector', 'Median', 'Altitude'],
selected = 0;
var form = svg.append('form');
var labelEnter = form.selectAll('span')
.data(triangleFunctions)
.enter().append('span');
labelEnter.append('input').attr({
type: 'radio',
class: 'shape',
name: 'mode',
value: function(d, i) {return i;}
});
labelEnter.append("label").text(function(d) {return d;});
You can see a jsbin of the code here.
The labels and inputs are not appearing.
You can use foreignObject (but be aware that it does not work in IE):
var form = svg.append("foreignObject").attr("width", "400")
.attr("height", "50").append("xhtml:body").append('form');
Note that body tag is required, and it also has to contain xhtml: part.
Demo: http://jsbin.com/mafikorezo/edit?js,output
I'm trying to set the width and height of a nvd3 multi bar chart programmatically using
chart.width(600);
chart.height(400);
See the example here:
http://jsfiddle.net/hPgyq/20/
As you can see this really messes up the chart. I know I can do this is CSS with:
#chart svg {
width: 600px;
height: 400px;
}
but I thought this was also possible using the width() and height() functions on the chart. Am I doing something wrong here or am I mis-using the two functions?
Yes it is possible, like you have specified the width & height of the chart, you have to use the d3.select and set its width & height attribute.
Changes to the code are below and there is a version of the code here
function visualizeData(data) {
nv.addGraph(function() {
var width = 600, height = 400;
chart = nv.models.multiBarChart().x(function(d) {
return d.x;
}).y(function(d) {
return d.y;
}).color(['#aec7e8', '#7b94b5', '#486192']).stacked(true)
//.margin({top:150,right:150,bottom:150,left:150})
.width(width).height(height);
chart.multibar.hideable(false);
chart.xAxis.showMaxMin(true).tickFormat(d3.format(',f'));
chart.yAxis.tickFormat(d3.format(',.1f'));
d3.select('#chart svg').datum(data).transition().duration(500).call(chart).style({ 'width': width, 'height': height });
nv.utils.windowResize(chart.update);
return chart;
});
}
For the AngularJs version (angular-nvd3), I had to add the height either in chart options and as an attribute:
chart.html
<nvd3 options='vm.chartOptions' data='vm.chartData' height="250" config="vm.chartConfig">
</nvd3>
chart.controller.js
vm.chartOptions = {
chart : {
height : 250,
type : "pieChart",
donut : true,
showLegend : false,
//The rest of the configuration
};
As it is told in the comments, first seems to control the height of the inner svg and the second does the global chart height.
I am new to SVG, so sorry if this is a bit of a noob question. I am trying to figure out how to get an image to display with the full width and height of the referenced image. I am using D3.js to build a graph and I want a logo to appear in the corner. The problem is that the image href will be set using javascript, so the image being referenced is never a fixed width or height. What I am wanting is the image to display in it's full width and height, not scaled up or down. What I was hoping for is the ability to automatically set the width and height of the image based on it's content, such as setting the width and height attributes to auto. This however just results in the image not being shown.
d3.select("body")
.append("svg")
.attr('id','mySVG')
.attr({
"width": "100%",
"height": "100%"
})
.attr("viewBox", "0 0 " + width + " " + height )
.attr("preserveAspectRatio", "none");
d3.select('#mySVG')
.append('image')
.attr('image-rendering','optimizeQuality')
.attr('height','auto') <--- This does not work
.attr('width','auto') <--- This does not work
.attr('xlink:href', logoUrl)
.attr('x','0')
.attr('y','0');
How would I go about specifying that the SVG image width and height must be dynamically determined based on the referenced image size?
I don't think 'auto' is a valid value for the 'length' attr of a svg image element. Take a look at the spec here. You might want to use '100%'
You could load the image then inspect the width and height onload.
JSFiddle: http://jsfiddle.net/WQBPC/4/
var logoUrl = 'http://placehold.it/100x50&text=Logo';
//SVG Setup stuff
var svg = d3.select("body").append("svg")
.attr('id','mySVG')
.attr({
"width": '100%',
"height": '100%'
})
var svg_img= svg.append('image')
.attr('image-rendering','optimizeQuality')
.attr('x','0')
.attr('y','0');
//Load image and get size.
var img = new Image();
img.src = logoUrl;
img.onload = function() {
var width = this.width;
var height = this.height;
svg_img .attr('height', height)
.attr('width',width)
.attr('xlink:href', logoUrl)
}
d3.select("svg")
.append("image")
.attr("id", "myImage")
.attr("xlink:href", "myImage.png")
.on("load", function(d) {
var myImage = new Image();
myImage.onload = function() {
d3.select("#myImage")
.attr("width", this.width)
.attr("height", this.height);
}
myImage.src = "myImage.png";
});
It's a couple years since this has been asked but I'm currently trying to determine some things about the use of auto as a value for width or height myself and thought I would share what I've found. According to Amelia Bellamy-Royds' 2015 article on scaling SVGs and the codepen example she provides, if you put auto in as either the width or the height value of your <svg>, along with a value for the viewBox, you should be able to see the content scaling proportionately. Unfortunately, she also points out that at the time this only worked in "Blink/Firefox" browsers. Blink is a fork of part of WebKit, so it's possible that by now Chrome will support this as well. I am seeing behavior in Chrome which would seem to support this possibility, but I'm also getting an error so YMMV.
I wanted to add a tool-tip to an image that is rendered using:
image (String source, Number x, Number y, Number width, Number height) api.
I couldn't figure out a way to do this, I am using org.moxieapps.gwt.highcharts API's to
create high charts in my GWT app.
Use chart.renderer.text and chart.renderer.rect to draw and position your own custom tooltip based on the position of the image.
This is a sample code snippet I used to display a tooltip for an image which is generated using chart.renderer.image -
marker = chart.renderer.image(src, x, y, imageSize, imageSize)
.on('click', function() {`enter code here`
})
.attr({
zIndex: 100
})
.on('mouseover', function() {
//Call back for image mouse hover
//Draw a text relative to Image X and Y
text = chart.renderer.text("Your tooltip Text",X, Y)
.add();
var box = text.getBBox();
//Now draw a box surrounding the tool tip text
textBG = chart.renderer.rect(box.x, box.y,box.width, box.height, 5)
.attr({
fill: '#FFFFEF',
stroke: 'gray',
'stroke-width': 1,
zIndex: 4
})
.add();
})
.on('mouseout', function() {
//Call back for mouse out on the image
//Destroy Both markers text and textBG on mouse out
//Make text and textBG as global functions for access accross functions
text.destroy();
textBG.destroy();
})
.add();
In this way you can create custom tooltip for images.
I used this link for syntax of adding tooltip text and its back ground to the chart.