Possible to build an svg that has fluid horizontal scaling, similar to old table-slice method?
I'm answering this because I had to do the something similar.
Yes, you can do it with just SVG. The key attributes are viewBox
and preserveAspectRatio
. preserveAspectRatio="xMaxYMid"
keeps the rectangle to the right and xMinYMid
keeps the rectangle to the left. Set the viewBox
to be the desired size of the rectangles on the end.
This has been tested in Chrome, Firefox, and IE.
Here is a plunker demo.
Note that if the change the height of the svg to 100% instead of 20px you can make the image scale with a containing html div
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<svg width="100%" height="20px" version="1.0" state='normal'
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<!-- The right head -->
<svg class='head input-source' id='right'
height="100%"
width='100%'
viewBox="0 0 15 30"
preserveAspectRatio="xMaxYMid"
>
<rect width="100%" height="100%"/>
</svg>
<!-- The left head -->
<svg class='head input-source' id='left'
height="100%"
width='100%'
viewBox="0 0 15 30"
preserveAspectRatio="xMinYMid"
>
<rect width="100%" height="100%"/>
</svg>
</defs>
<svg
class='input-source'
stroke='black'
stroke-width='0'
fill="green">
<rect x="2" y="20%" width="100%" height="60%"
stroke='black'
stroke-width='0'
>
</rect>
<use xlink:href='#right'/>
<use xlink:href='#left'/>
</svg>
</svg>
Is there a way to apply 9-patch / scale-9 principles in SVG?
I wrote about it on my blog, it's possible in a "perfect" way when you are willing to sacrifice IE and an "almost" way that works in IE as well as long as you can live with a not so perfect solution: http://w3.eleqtriq.com/2014/03/the-holy-grail-of-image-scaling/
responsive dc.js chart is taking over the whole window
Thanks for posting an example! The bug doesn't show up in the SO code snippet feature unless you go to full page mode. I found your fiddle easier to work with.
Note: this is a complete rewrite of my previous answer, which was not clear.
1. Using ResizeObserver
updated 4/28/20
As of Safari 13.1 (released March 24 2020) all modern browsers support ResizeObserver. This is the cleanest way to detect chart resizing.
I recommend
- Use a top-down layout such as flexbox or grid to position the divs for your charts
- Use
ResizeObserver
to determine when the div has changed size - Tell the charts to detect the chart div size using
.width(null).height(null)
There is currently one resizing example that does this.
The special value null
tells the chart to make the SVG node the same size as its parent div:
chart1.width(null)
.height(null)
The callback uses a helper function to disable transitions, because transitions just slow resizing down and make it look clunky:
const callback = chart => entries => {
redraw_chart_no_transitions(
chart
.width(null)
.height(null)
.rescale());
};
Setting up the observer looks like
new ResizeObserver(callback(chart1)).observe(d3.select('#test1').node());
Please see the example for more details.
2. Using window.onresize
The other resizing examples watch for window.onresize
because until recently that was the only efficient, reliable cross-browser way to detect changes.
They calculate chart sizes based on the window size, which works well if your layout is bottom-up, e.g. using the default float: left
layout.
Here is the function which sets this up:
function apply_resizing(chart, adjustX, adjustY, onresize) {
if(!Array.isArray(chart))
chart = [chart];
if(!isNaN(adjustX))
adjustX = (dx => x => x-dx)(adjustX);
adjustX = adjustX || (x => x);
if(!isNaN(adjustY))
adjustY = (dy => y => y-dy)(adjustY);
adjustY = adjustY || adjustX || (y => y);
chart.forEach(c => c.width(adjustX(window.innerWidth))
.height(adjustY(window.innerHeight)));
window.onresize = function () {
if (onresize) {
chart.forEach(onresize);
}
chart.forEach(c => {
c.width(adjustX(window.innerWidth))
.height(adjustY(window.innerHeight));
if (c.rescale) {
c.rescale();
}
});
redraw_chart_no_transitions(chart);
};
}
A single chart can be initialized like so:
apply_resizing(chart, 20);
This fills the window but makes the chart 20 pixels less wide.
The function can also take multiple charts in an array, and adjustment functions to support complicated layouts, like one where two charts should split the window vertically:
apply_resizing([heatmapChart, barChart], 20, y => y/2-fudge);
In D3 bar graph, y-axis ordinal scale is not aligning properly with bars
Problem 1:
Instead of this:
var _barThickness = 20;
Do this:
var _barThickness = scales.y.rangeBand();
Read here
If you want to regulate the thickness
Instead of this:
y: d3.scale.ordinal().rangeRoundBands([0, height], .1)
Do this:
y: d3.scale.ordinal().rangeRoundBands([0, height], .7)
Problem 2:
Incorrect transform.
Instead of this:
var rect = bar.enter()
.append('g')
.attr('transform', function(d, i) {
return 'translate(0,' + parseInt(i * _barThickness + 2) + ')';
});
Do this:
var rect = bar.enter()
.append('g');
Problem 3:
Incorrect calculation of y for the bars.
.attr('y', function(d, i) {
return (i * _barThickness);
})
Do this:
.attr('y', function(d, i) {
return scales.y(d.label);
})
working code here
Related Topics
Difference Between Baseline of Empty and Non-Empty Inline Blocks
What's the Difference Between CSS Inherit and Initial
How Does CSS Clearing Really Work
Table with Rowspan Hover and Zebra Effect
How to Visually Indicate Current Page in ASP.NET MVC
Edited Chrome Extension - Chrome Thinks It Is Malware
Darkening an Image with CSS (In Any Shape)
CSS Is Looking Different on Heroku
Text-Overflow: Ellipsis Doesn't Appear to Be Working
Incremental Slides Do Not Work with a Two-Column Layout
Grayscale Image with CSS on Safari 5.X
How Can a <Label> Completely Fill Its Parent <Td>
How Did CSS 'Content' Property Work for 'Img' Element in Webkit
Twitter Bootstrap Responsive Carousel with Multiple Items
Using Grunt Grunt-Contrib-Less) for Compiling Bootstrap 3.1 Less in Visual Studio 2013