I'm trying to change width of d3 tree chart when it expands?
Example jsfiddle.
Thanks!
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 960 - margin.right - margin.left,
height = 800 - margin.top - margin.bottom;
Related
I have a custom clipping, not default one. In my case I want to see image that out of clipping area and watermark. All works fine, but I can't change background color of empty area behind my image.
Here's working fiddle.
I've tried to set c.backgroundColor = 'red' or c.overlayColor = 'red', but it doesnt work.
EDIT: example of solution could be found in this fiddle.
ItÂ's not working because, you have set the globalCompositeOperation property to destination-atop for the image object, which changes the drawing destination of the background color. There is no need to set this property for the image object at all.
Here is the working version of your code ...
var c = new fabric.Canvas('c');
c.setBackgroundColor('white'); //set canvas background color
var clip = {
left: 100,
top: 100,
right: c.getWidth() - 100,
bottom: c.getHeight() - 100
}
var rb = new fabric.Path('M 0 0 H ' + c.getWidth() + ' V ' + clip.top + ' H ' + clip.left + ' V ' + clip.bottom + ' H ' + clip.right + ' V ' + clip.top + ' H ' + c.getWidth() + ' V ' + c.getHeight() + ' H 0 Z', {
left: 0,
top: 0,
fill: 'rgba(100,50,31,0.3)'
});
var circle = new fabric.Circle({
left: clip.right - 40,
top: clip.bottom - 40,
radius: 40,
fill: 'bisque'
});
var g = new fabric.Group([rb, circle], {
left: 0,
top: 0
});
c.setOverlayImage(g);
fabric.Image.fromURL('data:image/png;base64,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', function(fimg) {
c.add(fimg.set({
left: clip.left - 50,
top: clip.top - 50,
//globalCompositeOperation: 'destination-atop' //<-- do not set this
}));
c.setActiveObject(c.item(0));
})
c.renderAll();
fabric.Canvas.prototype.cropImage = function(format, quality, x, y, width, height) {
var canvasEl = this.lowerCanvasEl || this.upperCanvasEl;
this.deactivateAll().renderAll(true);
var printEl = canvasEl;
// Only use extra canvas if any optional param is given
if (x || y || width || height) {
// Defaults
x = x || 0;
y = y || 0;
width = width || canvasEl.width - x;
height = height || canvasEl.height - y;
// create printCanvas if necessary
if (!fabric.printCanvas)
fabric.printCanvas = document.createElement('canvas');
printEl = fabric.printCanvas;
// Calculate spaces over canvas bounds
var d = {
left: (x > 0) ? 0 : -x,
top: (y > 0) ? 0 : -y,
right: (x + width < canvasEl.width) ? 0 : (width + x) - canvasEl.width,
bottom: (y + height < canvasEl.height) ? 0 : (height + y) - canvasEl.height
};
// Print section
printEl.width = width;
printEl.height = height;
printEl.getContext('2d').drawImage(canvasEl,
x + d.left, y + d.top, width - d.right - d.left, height - d.bottom - d.top,
d.left, d.top, width - d.right - d.left, height - d.bottom - d.top);
}
var data = (fabric.StaticCanvas.supports('toDataURLWithQuality')) ? printEl.toDataURL('image/' + format, quality) : printEl.toDataURL('image/' + format);
this.contextTop && this.clearContext(this.contextTop);
this.renderAll();
return data;
};
$('#clip').click(function() {
window.open(c.cropImage('png', 75, clip.left, clip.top, clip.right - clip.left, clip.bottom - clip.top));
});
canvas{outline: 2px solid black;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<button id="clip">
Clip
</button>
and a JSFiddle
I've created a scatter plot in d3. The problem is that the y axis label does not appear in firefox and chrome (works fine in IE). I've tried doing things like making the svg width 100%, but for some reason the label always gets cut off.
<div id="TimeSeriesChartDiv" style="display: inline; float: right; width: 650px;
height: 415px">
</div>
//Width and height
var w = 600;
var h = 300;
var padding = 30;
var margin = { top: 20, right: 20, bottom: 30, left: 20 };
var df = d3.time.format("%b-%y");
//Create scale functions
var xScale = d3.time.scale()
.domain([d3.min(dataset, function (d) { return d[0]; }), d3.max(dataset, function (d) { return d[0]; })])
.range([padding, w - padding * 2])
.nice(5);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function (d) { return d[1]; })])
.range([h - padding, padding]);
//Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5)
.tickFormat(df);
//Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//Create SVG element
var svg = d3.select("#TimeSeriesChartDiv")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom);
//Create X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(20," + (h - padding) + ")")
.call(xAxis);
//Create Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + 50 + ",0)")
.call(yAxis);
svg.append("text")
.attr("class", "axislabel")
.attr("text-anchor", "end")
.attr("x", w / 2)
.attr("y", h + 8)
.text("Date");
svg.append("text")//-->>this is the text that gets cut off
.attr("class", "axislabel")
.attr("text-anchor", "end")
.attr("x", -100)
.attr("y", -15)
//.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text(unit);
Any ideas would be much appreciated. Thanks
You are using negative coordinates for your text, which means they get drawn outside the SVG. It seems that IE9 doesn't seem to clip thing to the SVG area, other browsers do. The best solution is to add enough padding to your graph so that your text can be drawn inside the SVG. Disabling the clipping does not seem to be supported in all browsers.
Thanks Jan -- with additional help from:
http://www.d3noob.org/2012/12/adding-axis-labels-to-d3js-graph.html
this worked:
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("class", "axislabel")
.attr("text-anchor", "middle")
.attr("x", 0 - (h / 2))
.attr("y",0)//any negative value here wouldnt display in ff or chrome
.attr("dy", "1em")
.text(unit);
I'm having difficulty determining the starting coordinate of the bounding box for the svg text element that corresponds to the label for a D3.js ordinal x-axis.
From the current code the text label DOM node x attributes have values of 0. However the label text is translated. Thus I would use svg.selectAll("g.x.axis g.tick.major").attr("transform") to determine the transform attributes of the label elements. I suppose I could just glean information those return values. Is there an easier method for this?
Here's an example DOM element from the code.
<g class="tick major" transform="translate(73.33333333333333,0)" style="opacity: 1;"><line y2="6" x2="0">
<line y2="6" x2="0"></line>
<text y="9" x="0" dy=".71em" style="text-anchor: middle;">banana</text>
</g>
My script:
var margin = {top: 100, right: 100, bottom: 100, left: 100},
width = 310 - margin.left - margin.right,
height = 200 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(["apple", "orange", "banana", "grapefruit"])
.rangePoints([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.call(xAxis);
console.log(svg.selectAll("g.x.axis g.tick.major")
.attr("transform"))
js and I am trying to figure out how to draw a discrete number of rectangles in an SVG element. It could be 5 rectangles to a million. What is the best way to go about this? Should I be using the Ordinal scale since I have a discrete number of rectangles or should I be using the linear scale? So I'm thinking that the width of the rectangles should shrink as the number of rectangles grows larger.
You have to compute the layout and create the appropriate scales. For example:
var width = 300,
height = 20,
margin = 2,
nRect = 20,
rectWidth = (width - (nRect - 1) * margin) / nRect,
svg = d3.select('#chart').append('svg')
.attr('width', width)
.attr('height', height);
var data = d3.range(nRect),
posScale = d3.scale.linear()
.domain(d3.extent(data))
.range([0, width - rectWidth]);
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x', posScale)
.attr('width', rectWidth)
.attr('height', height);
I wrote a small jsfiddle with this code: http://jsfiddle.net/pnavarrc/CA7rY/
I know raphael can create paths, but not lines. I know d3 can create both.
I would like to create a box and whisker chart, similar to this one, but horizontal instead of vertical. I have json data in the form:
{
"lowestValue":"53",
"lowerQuartile":"63",
"medianValue":"73",
"upperQuartile":"80",
"highestValue":"99",
"targetValue":"80"
},
...
How can I create a (or several) box and whisker plot(s) with d34raphael or with pure raphael, so that it will display properly in IE7/IE8?
Here is a picture of the end goal:
The path is such a similar primitive that it seems like it would be easy to recreate such a graph using raw Raphael (which seems increasingly to be my preference these days). Consider such a utility function as this:
function whisker( paper, x, y, width, height, data )
{
var x1 = x + data.lowestValue * width / 100, x2 = x + data.highestValue * width / 100;
var outer_range = paper.path( [ "M", x1, y + height * 0.25, "L", x1, y + height * 0.75, "M", x1, y + height / 2, "L", x2, y + height / 2, "M", x2, y + height / 4, "L", x2, y + height * 0.75 ] ).attr( { fill : 'none', stroke: 'gray' } );
var inner_range = paper.rect( x + ( width * data.lowerQuartile / 100 ), y, width * ( data.upperQuartile - data.lowerQuartile ) / 100, height, 0 ).attr( { fill: 'lightgray', stroke: 'black' } );
var median = paper.path( [ "M", x + width * data.medianValue / 100, y, "L", x + width * data.medianValue / 100, y + height ] ).attr( { fill: 'none', stroke: 'black' } );;
var target = paper.circle( x + ( width * data.targetValue / 100 ), y + height / 2, height / 4 ).attr( { fill: 'black' } );
}
The sixth parameter is simply your json data. You would need to increment the y value for each whisker, of course. Here's the code in action on my website.