本文介绍了捕获/保存d3.js Sunburst图表的当前状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是d3.js的新手。我在d3.js zoomable sunburst图表中工作。当用户放大到一个特定的弧,我需要捕获这种状态的sunburst图。当用户回到sunburst图或加载图形时,他应该看到他离开的状态。



注意:我不想序列化svg元素来显示sunburst的状态。如果我序列化它,那么图表将是静态的,用户不能点击sunburst并遍历到其他弧。



建议的解决方案:
一个解决方案来到我的心灵模拟鼠标点击sunburst节点,直到最后一个节点用户看着。
我不能为此设计一个算法。
请指导我是否有其他解决方案。

解决方案

你说的方法很容易实现。我为它做了一个小样本。
单击开始保存按钮以开始保存Sunburst的状态。执行几个缩放操作后,单击停止保存按钮。您可以对图表进行任何进一步的更改。现在,点击加载按钮将显示图表的保存状态。



  var width = 500,height = 500,radius = Math.min(width,height)/ 2; var x = d3.scale.linear().range([0,2 * Math.PI]); var y = d3。 scale.sqrt().range([0,radius]); var color = d3.scale.category10(); var svg = d3.select(body)。append(svg).attr(width ,width).attr(height,height).append(g).attr(transform,translate(+ width / 2 +,+(height / 2 + 10)+)rotate (-90 0 0)); var partition = d3.layout.partition().value(function(d){return d.size;}); var arc = d3.svg.arc().startAngle d){return Math.max(0,Math.min(2 * Math.PI,x(dx))) Math.PI,x(dx + d.dx)));}).innerRadius(function(d){return Math.max(0,y(dy)); }; var set = partition.nodes(root); var g = 0; svg.selectAll(g).data(partition.nodes(root)).enter()。append(g); var path = g.append(path).attr(d .style(fill,function(d){return color((d.children?d:d.parent).name);}).on(click,click); var text = g.append文本).attr(x,function(d){return y(dy);}).attr(dx,6)// margin .attr(dy,.35em)/ / vertical-align .attr(transform,function(d){returnrotate(+ computeTextRotation(d)+);}).text(function(d){return d.name;}).style (fill,white); function computeTextRotation(d){var angle = x(dx + d.dx / 2) -  Math.PI /返回角度/ Math.PI * 180; } var saveData = false; var savedData = []; d3.select(#saveBtn)。on(click,function(){if(d3.select(this).attr(value)==开始保存){savedData = []; d3.select(this).attr(value,Stop Save); saveData = true;} else {d3.select(this).attr(value,开始保存); saveData = false;}}); d3.select(#loadBtn)。on(click,function(){var root = g.filter(function(d){return d.name = =Root})。data(); click(root [0]); savedData.forEach(function(val){var node = g.filter(function(d,i){return i == val})。 data(); click(node [0]);});}); function click(d,i){if(saveData){if(d.name ==Root){savedData = [] } else {savedData.push(i); }} //淡出所有文本元素if(d.size!== undefined){d.size + = 100; }; text.transition()。attr(opacity,0); path.transition().duration(750).attrTween(d,arcTween(d)).each(end,function(e,i){//检查动画元素的数据e是否在可见角度在d中给出的范围if(ex> = dx&& ex<(dx + d.dx)){//获得相关文本元素的选择var arcText = d3.select(this.parentNode).select (text); //淡入文本元素并重新计算位置arcText.transition()。duration(750).attr(opacity,1).attr(transform,function + computeTextRotation(e)+)}).attr(x,function(d){return y(dy);});}}); } // var wrapLinebreaks = function(t,d,width){alert(0)var el = d3.select(t); var p = d3.select(t.parentNode); p.append(g).attr(x,function(d){return y(dy);}).attr(transform,function(d){returnrotate(+ computeTextRotation(d) +);}).append(foreignObject).attr('x',-width / 2).attr(width,width).attr(height,200).append p).attr('style','word-wrap:break-word; text-align:center;').html(d.name); alert(1)el.remove(); alert(2)}; d3.select(self.frameElement).style(height,height +px); //插值缩放函数arcTween(d){var xd = d3.interpolate(x.domain (y.domain(),[dy,1]),yr = d3.interpolate(y.range(),[dy?20: 0,radius]); return function(d,i){return i? function(t){return arc(d); }:function(t){x.domain(xd(t)); y.domain(yd(t))。range(yr(t)); return arc(d); }; };} function getData(){return {name:Root,children:[{name:A1,children:[{name:B1,size 30},{name:B2,size:40},{name:B3,children:[{name:C1,size:10} name:C2,size:15}]}],{name:A2,children name:B5,size:30},{name:B6,size:10}]},{name:A3,children:[{name :B7,size:50},{name:B8,size:15}]}]}};  
  path {stroke:#fff; fill-rule:evenodd;}  
 < script src = https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js\"> ;</script> ;<div id =main>< / div>< ; input type =buttonvalue =Start Saveid =saveBtn/>< input type =buttonvalue =Loadid =loadBtn/>  / pre> 



我不知道你打算在哪里保存sunburst的状态。我建议是一个不错的选择。



希望这有帮助。


I am a newbie to d3.js . I am working in d3.js zoomable sunburst chart http://bl.ocks.org/mbostock/4348373. When the user zoom into a particular arc and I need to capture this state of the sunburst diagram . When the user comes back to the sunburst diagram or load the graph again he should see the state where he left.

Note : I dont want to serialise the svg elements to show the state of the sunburst. If i serialise it then the chart will be static and user cant click on the sunburst and traverse to other arcs.

Proposed Solution : one solution came to my mind is simulate mouse clicks on the sunburst nodes till the last node user looks into. I am not able to devise an algorithm for this . Please guide me whether any other solution is possible ..

解决方案

The approach you said is easy to implement. I have made a small sample for it. Click the Start Save button to start saving the state of Sunburst. Click Stop Save button after performing a few zooming actions. You can make any further changes to the chart. Now, clicking Load button will show you the saved state of the chart.

var width = 500,
    height = 500,
    radius = Math.min(width, height) / 2;


var x = d3.scale.linear()
    .range([0, 2 * Math.PI]);

var y = d3.scale.sqrt()
    .range([0, radius]);

var color = d3.scale.category10();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ") rotate(-90 0 0)");

var partition = d3.layout.partition()
    .value(function(d) {
        return d.size;
    });

var arc = d3.svg.arc()
    .startAngle(function(d) {
        return Math.max(0, Math.min(2 * Math.PI, x(d.x)));
    })
    .endAngle(function(d) {
        return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
    })
    .innerRadius(function(d) {
        return Math.max(0, y(d.y));
    })
    .outerRadius(function(d) {
        return Math.max(0, y(d.y + d.dy));
    });

var root = getData();
var savedData = partition.nodes(root);
var g = svg.selectAll("g")
    .data(partition.nodes(root))
    .enter().append("g");

var path = g.append("path")
    .attr("d", arc)
    .style("fill", function(d) {
        return color((d.children ? d : d.parent).name);
    })
    .on("click", click);

var text = g.append("text")
    .attr("x", function(d) {
        return y(d.y);
    })
    .attr("dx", "6") // margin
    .attr("dy", ".35em") // vertical-align
    .attr("transform", function(d) {
        return "rotate(" + computeTextRotation(d) + ")";
    })
    .text(function(d) {
        return d.name;
    })
    .style("fill", "white");

function computeTextRotation(d) {
        var angle = x(d.x + d.dx / 2) - Math.PI / 2;
        return angle / Math.PI * 180;
    }
    
var saveData = false;
var savedData = [];
d3.select("#saveBtn").on("click", function() {
    if (d3.select(this).attr("value") == "Start Save") {
        savedData = [];
        d3.select(this).attr("value", "Stop Save");
        saveData = true;
    } else {
        d3.select(this).attr("value", "Start Save");
        saveData = false;
    }
});
d3.select("#loadBtn").on("click", function() {
    var root = g.filter(function(d) {
        return d.name == "Root"
    }).data();
    click(root[0]);
    savedData.forEach(function(val) {
        var node = g.filter(function(d, i) {
            return i == val
        }).data();
        click(node[0]);
    });
});

function click(d, i) {       
        if (saveData) {
            if(d.name=="Root"){
               savedData = [];
            } else{
                savedData.push(i);
            }
        }
        // fade out all text elements
        if (d.size !== undefined) {
            d.size += 100;
        };
        text.transition().attr("opacity", 0);

        path.transition()
            .duration(750)
            .attrTween("d", arcTween(d))
            .each("end", function(e, i) {
                // check if the animated element's data e lies within the visible angle span given in d
                if (e.x >= d.x && e.x < (d.x + d.dx)) {
                    // get a selection of the associated text element
                    var arcText = d3.select(this.parentNode).select("text");
                    // fade in the text element and recalculate positions
                    arcText.transition().duration(750)
                        .attr("opacity", 1)
                        .attr("transform", function() {
                            return "rotate(" + computeTextRotation(e) + ")"
                        })
                        .attr("x", function(d) {
                            return y(d.y);
                        });
                }
            });
    } 

// Word wrap!
var insertLinebreaks = function(t, d, width) {
    alert(0)
    var el = d3.select(t);
    var p = d3.select(t.parentNode);
    p.append("g")
        .attr("x", function(d) {
            return y(d.y);
        })          
        .attr("transform", function(d) {
            return "rotate(" + computeTextRotation(d) + ")";
        })           
        .append("foreignObject")
        .attr('x', -width / 2)
        .attr("width", width)
        .attr("height", 200)
        .append("xhtml:p")
        .attr('style', 'word-wrap: break-word; text-align:center;')
        .html(d.name);
    alert(1)
    el.remove();
    alert(2)
};



d3.select(self.frameElement).style("height", height + "px");

// Interpolate the scales!
function arcTween(d) {
    var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
        yd = d3.interpolate(y.domain(), [d.y, 1]),
        yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
    return function(d, i) {
        return i ? function(t) {
            return arc(d);
        } : function(t) {
            x.domain(xd(t));
            y.domain(yd(t)).range(yr(t));
            return arc(d);
        };
    };
}

function getData() {
    return {
        "name": "Root",
        "children": [{
            "name": "A1",
            "children": [{
                "name": "B1",
                "size": 30
            }, {
                "name": "B2",
                "size": 40
            }, {
                "name": "B3",
                "children": [{
                    "name": "C1",
                    "size": 10
                }, {
                    "name": "C2",
                    "size": 15
                }]
            }]
        }, {
            "name": "A2",
            "children": [{
                "name": "B4",
                "size": 40
            }, {
                "name": "B5",
                "size": 30
            }, {
                "name": "B6",
                "size": 10
            }]
        }, {
            "name": "A3",
            "children": [{
                    "name": "B7",
                    "size": 50
                }, {
                    "name": "B8",
                    "size": 15
                }

            ]
        }]
    }
};
path {
    stroke: #fff;
    fill-rule: evenodd;
}
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="main"></div>
<input type="button" value="Start Save" id="saveBtn"/>
<input type="button" value="Load" id="loadBtn"/>

I don't know where do you plan to save the state of the sunburst. I would suggest that Localstorage would be a nice option.

Hope this helps.

这篇关于捕获/保存d3.js Sunburst图表的当前状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 20:56