javascript - 在调整大小时重绘 SVG

标签 javascript svg d3.js

我正在尝试在 d3 中重新绘制窗口调整大小的 SVG 图表,但没有使用 viewBoxpreserveAspectRatio 参数(我不喜欢他们处理文本的方式).

我还试图通过 Bostock 的 suggestion 坚持使用 d3 的数据绑定(bind)设计。附加单个元素时(不基于支持的数据)。

我有一些事情可以归结为这个 ( jsFiddle )。然而,SVG 元素的宽度/高度永远不会更新。

HTML

<div class="chart-container">
    <button class="user-option">Some User Options</button>
    <div class="svg-container"></div>
</div>

Javascript

$(window).on("resize", function () {
    draw();
});

function draw() {
    var container = d3.select('.chart-container');
    var drawWidth = Math.round(0.80 * container.node().clientWidth);
    var drawHeight = Math.round(drawWidth * (3 / 4)); // Fixing a 4/3 aspect ratio

    /*
     * Use an inner g element as the SVG canvas in order to set and forget margins.
     * See http://bl.ocks.org/mbostock/3019563
     */
    var margin = {
        top: 10,
        right: 30,
        bottom: 50,
        left: 40
    };
    var width = drawWidth - margin.left - margin.right;
    var height = drawHeight - margin.top - margin.bottom;

    var svg = container.select(".svg-container").selectAll('svg')
            .data([0]) // Single data element to create SVG if it doesn't exist
        .enter().append("svg")
            .attr("width", drawWidth)
            .attr("height", drawHeight)
        .append("g")
            .attr("class", "canvas")
            // jsFiddle doesn't translate correctly, maybe because of frames???
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    console.debug(svg.node()); // null on resize???

    // Add some random SVG element
    svg.selectAll('rect')
            .data([0]) // Single data element to create SVG if it doesn't exist
        .enter().append('rect')
            .attr({
                x: 0,
                y: 0,
                width: drawWidth - margin.right - margin.left,
                height: drawHeight - margin.bottom - margin.top
            });
}

最佳答案

这里的根本问题是您的 svg 变量没有被分配 <svg>元素选择,它被分配链式方法调用的最终结果,第一次是 <g>元素,之后是空的,因为没有“输入”选择。

所以首先要做的是更改为

var svg = container.select(".svg-container").selectAll('svg').data([0]);
// now you have a reference to the svg selection

第一次执行时,更新选择将为空,输入选择将只有一个元素。然后将其绑定(bind)到一个新的 <svg>元素:

svg.enter()
    .append("svg")
    .append("g")
// note that from this point you're setting attributes on the <g>, not the <svg>
        .attr("class", "canvas")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

此附加操作还将元素添加到存储在 svg 中的更新选择中.

调整大小时,输入选择将为空,但更新选择在svg将已经包含现有的 <svg>元素。所以无论哪种方式,此时您都可以在 svg 上设置属性选择 - 它适用于这两种情况。

svg.attr("width", drawWidth)
   .attr("height", drawHeight);

更新 fiddle http://jsfiddle.net/3dgn5pz8/5/

关于javascript - 在调整大小时重绘 SVG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25555257/

相关文章:

javascript - 如何运行依赖于第一个 api 中设置的变量的 api?

d3.js:强制布局中建议的节点位置

javascript - 未捕获的类型错误 : d3. scaleOrdinal 不是函数

javascript - Sankey 图,在 PHP 中使用查询创建多维数组

css - 带有渐变叠加和背景图像的 SVG 圆 Angular 三 Angular 形

javascript - 使用 CSS 动画使元素在页面加载后隐藏 n 秒

javascript - 动画功能 : change div width by using radio buttons

javascript - Jquery 验证 submitHandler 没有被调用

html - 如何在 snap.svg 中使用多边形

HTML5 行无法使用 svg