首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在RAW中添加d3.js交互式可缩放树状图

问在RAW中添加d3.js交互式可缩放树状图
EN

Stack Overflow用户
提问于 2015-08-13 08:09:54
回答 1查看 819关注 0票数 0

有没有办法在未加工中添加可缩放的树状图。使用d3.js的回车更新退出模式在RAW中没有意义,因此如果没有此功能,是否可以在RAW.js中添加d3.js可缩放的树状图?

未加工的添加新图表文档说

这样,D3的输入-更新-退出模式在RAW的图表中没有太多的意义,因为当将选择传递给绘图函数时,选择始终是空的。因为RAW是用来制作非交互式可视化的工具,需要用矢量图形工具来阐述,所以这不应该被看作是一种限制,相反,它是一种简化图表绘图代码的方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-18 07:30:39

我已经能够添加可缩放的树状地图在生。下面是代码。

zoomableTreemap.js

代码语言:javascript
复制
(function(){

    var tree = raw.models.tree();

    var chart = raw.chart()
        .title('Zoomable Treemap')
        .description(
        "A space filling visualization of data hierarchies and proportion between elements. The different hierarchical levels create visual clusters through the subdivision into rectangles proportionally to each element's value. Treemaps are useful to represent the different proportion of nested hierarchical data structures.<br/>Based on <a href='http://bl.ocks.org/mbostock/4063582'>http://bl.ocks.org/mbostock/4063582</a>")
        .thumbnail("/raw/imgs/treemap.png")
        .category('Hierarchies')
        .model(tree)

    var rawWidth = chart.number()
        .title('Width')
        .defaultValue(100)
        .fitToWidth(true)

    var rawHeight = chart.number()
        .title("Height")
        .defaultValue(500)

    var padding = chart.number()
        .title("Padding")
        .defaultValue(0)

    var colors = chart.color()
        .title("Color scale")

    chart.draw(function (selection, root){

        root.name = 'ZoomableTree';

        var margin = {top: 20, right: 0, bottom: 0, left: 0},
            width = +rawWidth(),
            height = +rawHeight() - margin.top - margin.bottom,
            formatNumber = d3.format(",d"),
            transitioning;

        var x = d3.scale.linear()
            .domain([0, width])
            .range([0, width]);

        var y = d3.scale.linear()
            .domain([0, height])
            .range([0, height]);

        console.log(padding());
        console.log(+padding());
        var treemap = d3.layout.treemap()
            .padding(+padding())
            .children(function(d, depth) { return depth ? null : d._children; })
            .sort(function(a, b) { return a.value - b.value; })
            .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
            // Values are required in d3 treemap layout
            // and our DB table do not have values field in it, so we are going to use 1 for all nodes.
            // The value decides the size/area of rectangle in d3 treemap layout so effectively we are going to have
            // even sized rectangles
            .value(function(d) { return 1; })
            .round(false);

        var svg = selection
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.bottom + margin.top)
            .style("margin-left", -margin.left + "px")
            .style("margin.right", -margin.right + "px")
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .style("shape-rendering", "crispEdges")


        var grandparent = svg.append("g")
            .attr("class", "grandparent");

        grandparent.append("rect")
            .attr("y", -margin.top)
            .attr("width", width)
            .attr("height", margin.top)
            .style("fill", function (d) { return colors()(d.color); })
            .style("stroke","#fff")

        grandparent.append("text")
            .attr("x", 6)
            .attr("y", 6 - margin.top)
            .attr("dy", ".75em");

            initialize(root);
            //console.log(root);
            //throw '';
            accumulate(root);
            layout(root);
            display(root);

            function initialize(root) {
                root.x = root.y = 0;
                root.dx = width;
                root.dy = height;
                root.depth = 0;
            }

            // Aggregate the values for internal nodes. This is normally done by the
            // treemap layout, but not here because  of our custom implementation.
            // We also take a snapshot of the original children (_children) to avoid
            // the children being overwritten when when layout is computed.
            function accumulate(d) {
                return (d._children = d.children)
                    ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0)
                    : d.value;
            }

            // Compute the treemap layout recursively such that each group of siblings
            // uses the same size (1×1) rather than the dimensions of the parent cell.
            // This optimizes the layout for the current zoom state. Note that a wrapper
            // object is created for the parent node for each group of siblings so that
            // the parent’s dimensions are not discarded as we recurse. Since each group
            // of sibling was laid out in 1×1, we must rescale to fit using absolute
            // coordinates. This lets us use a viewport to zoom.
            function layout(d) {
                if (d._children) {
                    //console.log(d);
                    //throw 'stop';
                    treemap.nodes({_children: d._children});
                    d._children.forEach(function(c) {
                        //console.log(d);
                        c.x = d.x + c.x * d.dx;
                        c.y = d.y + c.y * d.dy;
                        c.dx *= d.dx;
                        c.dy *= d.dy;
                        c.parent = d;
                        //console.log(c);
                        layout(c);
                    });
                }
            }

            function display(d) {
                grandparent
                    .datum(d.parent)
                    .on("click", transition)
                    .select("text")
                    .text(name(d));

                var g1 = svg.insert("g", ".grandparent")
                    .datum(d)
                    .attr("class", "depth");

                var g = g1.selectAll("g")
                    .data(d._children)
                    .enter().append("g");

                g.filter(function(d) { return d._children; })
                    .classed("children", true)
                    .on("click", transition);

                g.selectAll(".child")
                    .data(function(d) { return d._children || [d]; })
                    .enter().append("rect")
                    .attr("class", "child")
                    .call(rect);

                g.append("rect")
                    .attr("class", "parent")
                    .call(rect)
                    .append("title")
                    .text(function(d) { return formatNumber(d.value); })
                    .style("fill", function (d) { return colors()(d.color); })
                    .style("stroke","#fff")

                g.append("text")
                    .attr("dy", ".75em")
                    .text(function(d) { return d.name; })
                    .call(text);

                function transition(d) {
                    if (transitioning || !d) return;
                    transitioning = true;

                    var g2 = display(d),
                        t1 = g1.transition().duration(750),
                        t2 = g2.transition().duration(750);

                    // Update the domain only after entering new elements.
                    x.domain([d.x, d.x + d.dx]);
                    y.domain([d.y, d.y + d.dy]);

                    // Enable anti-aliasing during the transition.
                    svg.style("shape-rendering", null);

                    // Draw child nodes on top of parent nodes.
                    svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });

                    // Fade-in entering text.
                    g2.selectAll("text").style("fill-opacity", 0);

                    // Transition to the new view.
                    t1.selectAll("text").call(text).style("fill-opacity", 0);
                    t2.selectAll("text").call(text).style("fill-opacity", 1);
                    t1.selectAll("rect").call(rect);
                    t2.selectAll("rect").call(rect);

                    // Remove the old node when the transition is finished.
                    t1.remove().each("end", function() {
                        svg.style("shape-rendering", "crispEdges");
                        transitioning = false;
                    });
                }

                return g;
            }

            function text(text) {
                text.attr("x", function(d) { return x(d.x) + 6; })
                    .attr("y", function(d) { return y(d.y) + 6; });
            }

            function rect(rect) {
                rect.attr("x", function(d) { return x(d.x); })
                    .attr("y", function(d) { return y(d.y); })
                    .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
                    .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); })
                    .style("fill", function (d) { return colors()(d.color); })
                    .style("stroke","#fff");
            }

            function name(d) {
                return d.parent
                    ? name(d.parent) + "." + d.name
                    : d.name;
            }


    })
})();

chart.css

代码语言:javascript
复制
#chart {
    background: #ddd;
}

text {
    pointer-events: none;
}

.grandparent text {
    font-weight: bold;
}

rect {
    fill: none;
    stroke: #fff;
}

rect.parent,
.grandparent rect {
    stroke-width: 2px;
}

.grandparent rect {
    fill: orange;
}

.grandparent:hover rect {
    fill: #ee9700;
}

.children rect.parent,
.grandparent rect {
    cursor: pointer;
}

.children rect.parent {
    fill: #bbb;
    fill-opacity: .5;
}

.children:hover rect.child {
    fill: #bbb;
}

Index.html

只需在raw的索引页中包含css和js。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31982847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档