javascript - D3.js 动画与 jQuery 更新相结合

标签 javascript jquery d3.js

好的,所以我正在使用列出的大部分代码 here 。考虑到动画,我想做的是使用 jQuery 动态加载数据。但是,因为我将它包装在一个函数中,如下所示:

function dataGrab(){
    $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            url: 'somelink.php?param=someparam',
            dataType: 'text',
            async: true,
            data: "", 
            success: function (data) {


                buildGraph(data);

            },
            error: function (result) {
                alert("error");
            }

})
};

构建图托管问题中的代码副本,如下所示:

function buildGraph(pureData)
{

var temp = pureData;
var data = JSON.parse(temp);
var width = 500,
    height = 500;
var force = d3.layout.force()
    .size([width, height])
    .charge(function(d){
        var charge = -500;
        if (d.index === 0) charge = 10 * charge;
        return charge;
    })
    .linkDistance(d => d.distance)
    .on("tick", tick);
d3.selectAll("svg").remove();
var svg = d3.select("#orb")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "mainsvg");
var link = svg.selectAll(".link"),
    node = svg.selectAll(".node"),
    path = svg.selectAll(".path");
force.nodes(data.nodes)
    .links(data.links)
    .start();
var edges = link.data(data.links)
    .enter()
    .append("line")
    .attr("class", "link")
    .style("stroke", "grey")
    .style("pointer-events", "none");
node = node.data(data.nodes)
    .enter()
    .append("g");
node.append("circle")
    .attr("class", "circle")
    .attr("r", function(d) { if(d.r){ return d.r; } else { return "18";} })
    .attr("fill", function(d) { if(d.color) { return d.color; } else { return "#24b8e3";} })
    .attr("stroke", function(d) { if(d.color) { return d.color; } else { return "#24b8e3";} });
var linkwrap = node.append("a")
    .attr("href", "3");
linkwrap.append("image")
    .attr("class", "srcico")
    .attr("height", "16px")
    .attr("width", "16px")
    .attr("xlink:href", function(d) { if(d.icon.length > 25) { return d.icon; } });


function tick() {
    var link = svg.selectAll("line");
    var edgepaths = svg.selectAll(".edgepath");
    var edgelabels = svg.selectAll(".edgelabel");


    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    svg.selectAll(".circle")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
    svg.selectAll(".srcico")
        .attr("x", function(d) { return d.x-5; })
        .attr("y", function(d) { return d.y-8; });
    svg.selectAll(".notecap")
        .attr("x", function(d) { return d.x; })
        .attr("y", function(d) { return d.y; });
}
}


dataGrab();
var inter = setInterval(function() {

    dataGrab();
    setTimeout(function() {
        force.linkDistance(20);
        force.start().alpha(0.01);
    }, 2000);

}, 5000);

考虑到我的所有变量(例如 svgforce)都在 dataGrab() 范围内声明,我遇到了各种问题。我尝试过在外部声明它们,我尝试过在 setInterval 内部以相同的方式重新声明它们,但无论我做什么,都会发生一些疯狂的事情,或者我没有收到错误,但它没有不工作。我还尝试构建 1 个根节点(链接问题中示例中的灰色节点)并通过书面 ajax 仅更新其他节点,但它不起作用。所以我想做的就是问题的答案,只使用 jQuery。如果运行一次,此代码将运行良好,但是,更新部分是我遇到问题的地方。谢谢!

PS,为了澄清,或者为了避免单击链接,这是所需的结果,仅使用 jQuery

var data = {

    nodes: [
  	{"x": 250, "y": 250, "color": "green", "name":"TEST", "r":"28", "fixed":true},
    {"x": 120, "y": 150, "name":"forums.macrumors", "score": -12.2, "icon": ""},
    {"x": 140, "y": 150, "name":"delhidailynews", "score": -0.08, "icon": ""},
    {"x": 280, "y": 150, "name":"4-traders", "score": -0.055, "icon": ""},
    {"x": 300, "y": 150, "name":"phonearena", "score": 0.45, "icon": ""},
    {"x": 40, "y": 200, "name":"inga3.wordpress", "score": -0.27, "icon": ""},
    {"x": 70, "y": 200, "name":"kahinaweb.wordpress", "score": -0.28, "icon": ""},
    {"x": 100, "y": 200, "name":"bilqueessite.wordpress", "score": -0.3, "icon": ""},
    {"x": 130, "y": 200, "name":"beforeitsnews", "score": -0.72, "icon": ""},
    {"x": 380, "y": 200, "name":"yahoo", "score": -0.66, "icon": ""}    
    ],
   links: [
    {"source":  0, "target": 1, "distance": 180, "label": ""},
    {"source":  0, "target": 2, "distance": 180, "label": ""},
    {"source":  0, "target": 3, "distance": 180, "label": ""},
    {"source":  0, "target": 4, "distance": 180, "label": ""},
    {"source":  0, "target": 5, "distance": 180, "label": ""},
    {"source":  0, "target": 6, "distance": 180, "label": ""},
    {"source":  0, "target": 7, "distance": 180, "label": ""},
    {"source":  0, "target": 8, "distance": 180, "label": ""},
    {"source":  0, "target": 9, "distance": 180, "label": ""}
   

    
  ]
    };
  
var width = 500,
	height = 500;
var force = d3.layout.force()
	.size([width, height])
	.charge(function(d){
        var charge = -500;
        if (d.index === 0) charge = 10 * charge;
        return charge;
    })
	.linkDistance(d => d.distance)
	.on("tick", tick);

var svg = d3.select("#orb")
	.append("svg")
	.attr("width", width)
	.attr("height", height)
	.attr("class", "mainsvg");
var link = svg.selectAll(".link"),
	node = svg.selectAll(".node"),
	path = svg.selectAll(".path");

force.nodes(data.nodes)
	.links(data.links)
	.start();
var edges = link.data(data.links)
	.enter()
	.append("line")
	.attr("class", "link")
	.style("stroke", "grey")
	.style("pointer-events", "none");
node = node.data(data.nodes)
	.enter()
	.append("g");
node.append("circle")
	.attr("class", "circle")
	.attr("r", function(d) { if(d.r){ return d.r; } else { return "18";} })
	.attr("fill", function(d) { if(d.color) { return d.color; } else { return "orange";} })
	.attr("stroke", function(d) { if(d.color) { return d.color; } else { return "orange";} });
var linkwrap = node.append("a")
	.attr("href", "3");
linkwrap.append("image")
	.attr("class", "srcico")
	.attr("height", "16px")
	.attr("width", "16px")
	.attr("xlink:href", function(d) { return d.icon; });
linkwrap.append("text")
	.attr("fill", "white")
	.attr("stroke", "none")
	.attr("x", "232")
	.attr("y", "255")
    .text(function(d) { return d.ticker; });

function tick() {
	var link = svg.selectAll("line");
	var edgepaths = svg.selectAll(".edgepath");
	var edgelabels = svg.selectAll(".edgelabel");
	link.attr("x1", function(d) { return d.source.x; })
		.attr("y1", function(d) { return d.source.y; })
		.attr("x2", function(d) { return d.target.x; })
		.attr("y2", function(d) { return d.target.y; });

	svg.selectAll(".circle")
		.attr("cx", function(d) { return d.x; })
		.attr("cy", function(d) { return d.y; });
	svg.selectAll(".srcico")
		.attr("x", function(d) { return d.x-5; })
		.attr("y", function(d) { return d.y-8; });
	svg.selectAll(".notecap")
		.attr("x", function(d) { return d.x; })
		.attr("y", function(d) { return d.y; });
}
var inter = setInterval(function() {	
                updateData();
								setTimeout(function(){
									force.linkDistance(20);
									force.start().alpha(0.01);
								},2000);
        }, 5000); 

function updateData() {
var data = {

    nodes: [
  	{"x": 250, "y": 250, "color": "grey", "name":"TEST", "r":"28", "fixed":true},
    {"x": 120, "y": 210, "name":"", "score": -12.2, "icon": ""},
    {"x": 140, "y": 210, "name":"", "score": -0.08, "icon": ""},
    {"x": 280, "y": 210, "name":"", "score": -0.055, "icon": ""},
    {"x": 300, "y": 210, "name":"", "score": 0.45, "icon": ""},
    {"x": 40, "y": 200, "name":"", "score": -0.27, "icon": ""},
    {"x": 70, "y": 200, "name":"", "score": -0.28, "icon": ""},
    {"x": 100, "y": 200, "name":"", "score": -0.3, "icon": ""},
    {"x": 130, "y": 200, "name":"", "score": -0.72, "icon": ""},
    {"x": 380, "y": 200, "name":"", "score": -0.66, "icon": ""},
    {"x": 160, "y": 200, "name":"", "score": -0.317, "icon": ""},
    {"x": 280, "y": 200, "name":"", "score": -0.37, "icon": ""},
    {"x": 270, "y": 200, "name":"", "score": -0.49, "icon": ""},
    {"x": 340, "y": 200, "name":"", "score": -0.62, "icon": ""},
    {"x": 100, "y": 300, "name":"", "score": -0.31, "icon": ""},
    {"x": 140, "y": 300, "name":"", "score": -0.457, "icon": ""},
    {"x": 180, "y": 300, "name":"", "score": -0.472, "icon": ""},
    {"x": 280, "y": 300, "name":"", "score": -0.66, "icon": ""},   
    {"x": 320, "y": 300, "name":"", "score": -0.68, "icon": ""},
    {"x": 410, "y": 300, "name":"", "score": -0.8, "icon": ""},
    {"x": 260, "y": 300, "name":"", "score": -0.86, "icon": ""}
    ],
   links: [
    {"source":  0, "target": 1, "distance": 180, "label": ""},
    {"source":  0, "target": 2, "distance": 180, "label": ""},
    {"source":  0, "target": 3, "distance": 180, "label": ""},
    {"source":  0, "target": 4, "distance": 180, "label": ""},
    {"source":  0, "target": 5, "distance": 180, "label": ""},
    {"source":  0, "target": 6, "distance": 180, "label": ""},
    {"source":  0, "target": 7, "distance": 180, "label": ""},
    {"source":  0, "target": 8, "distance": 180, "label": ""},
    {"source":  0, "target": 9, "distance": 180, "label": ""},
    {"source":  0, "target": 10, "distance": 180, "label": ""},
    {"source":  0, "target": 11, "distance": 180, "label": ""},
    {"source":  0, "target": 12, "distance": 180, "label": ""},
    {"source":  0, "target": 13, "distance": 180, "label": ""},
    {"source":  0, "target": 14, "distance": 180, "label": ""},
    {"source":  0, "target": 15, "distance": 180, "label": ""},
    {"source":  0, "target": 16, "distance": 180, "label": ""},
    {"source":  0, "target": 17, "distance": 180, "label": ""},
    {"source":  0, "target": 18, "distance": 180, "label": ""},
    {"source":  0, "target": 19, "distance": 180, "label": ""},
    {"source":  0, "target": 20, "distance": 180, "label": ""}
  ]
    };

d3.selectAll(".mainsvg > *").remove();

var link = svg.selectAll(".link"),
	node = svg.selectAll(".node"),
	path = svg.selectAll(".path");
	
	force.linkDistance(d=>d.distance);


	force.nodes(data.nodes)
		.links(data.links)
		.start();
	var edges = link.data(data.links)
		.enter()
		.append("line")
		.attr("class", "link")
		.style("stroke", "grey")
		.style("pointer-events", "none");
	node = node.data(data.nodes)
		.enter()
		.append("g");
	node.append("circle")
		.attr("class", "circle")
		.attr("r", function(d) { if(d.r){ return d.r; } else { return "18";} })
		.attr("fill", function(d) { if(d.color) { return d.color; } else { return "orange";} })
		.attr("stroke", function(d) { if(d.color) { return d.color; } else { return "orange";} });
	var linkwrap = node.append("a")
		.attr("href", "3");
	linkwrap.append("image")
	.attr("class", "srcico")
	.attr("height", "16px")
	.attr("width", "16px")
		.attr("xlink:href", function(d) { return d.icon; });
	 linkwrap.append("text")
	 .attr("fill", "white")
	 .attr("stroke", "none")
	 .attr("x", "232")
	 .attr("y", "255")
    .text(function(d) { return d.ticker; });


}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="orb">
</div>

最佳答案

这就是我解决这个问题的方法。我已将构建图移到函数之外,以便仅正确定义变量。因此想象一下函数外部的完全相同的代码。 之后,使用完全相同的代码创建一个更新函数,例如 update(pureData){ 并使其看起来像这样(完整的绘制/更新代码):

var data = { // insert root node here or leave empty doesn't matter, we're keeping this outside the functions only to set d3 vars proper }
var width = 500,
    height = 500;
var force = d3.layout.force()
    .size([width, height])
    .charge(function(d){
        var charge = -500;
        if (d.index === 0) charge = 10 * charge;
        return charge;
    })
    .linkDistance(d => d.distance)
    .on("tick", tick);
var svg = d3.select("#holderIdHere")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("class", "mainsvg");
var link = svg.selectAll(".link"),
    node = svg.selectAll(".node"),
    path = svg.selectAll(".path");
force.nodes(data.nodes)
    .links(data.links)
    .start();
var edges = link.data(data.links)
    .enter()
    .append("line")
    .attr("class", "link")
    .style("stroke", "grey")
    .style("pointer-events", "none");
node = node.data(data.nodes)
    .enter()
    .append("g");
node.append("circle")
    .attr("class", "circle")
    .attr("r", function(d) { if(d.r){ return d.r; } else { return "18";} })
    .attr("fill", function(d) { if(d.color) { return d.color; } else { return "#24b8e3";} })
    .attr("stroke", function(d) { if(d.color) { return d.color; } else { return "#24b8e3";} });
var linkwrap = node.append("a")
    .attr("href", "3");
linkwrap.append("image")
    .attr("class", "srcico")
    .attr("height", "16px")
    .attr("width", "16px")
    .attr("xlink:href", function(d) { if(d.icon.length > 25) { return d.icon; } });


function tick() {
    var link = svg.selectAll("line");
    var edgepaths = svg.selectAll(".edgepath");
    var edgelabels = svg.selectAll(".edgelabel");


    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    svg.selectAll(".circle")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
    svg.selectAll(".srcico")
        .attr("x", function(d) { return d.x-5; })
        .attr("y", function(d) { return d.y-8; });
    svg.selectAll(".notecap")
        .attr("x", function(d) { return d.x; })
        .attr("y", function(d) { return d.y; });
}

function updateMe(newData)
{
  var data = newData;
d3.selectAll("#holderIdHere").remove();

var link = svg.selectAll(".link"),
    node = svg.selectAll(".node"),
    path = svg.selectAll(".path");
force.nodes(data.nodes)
    .links(data.links)
    .start();
var edges = link.data(data.links)
    .enter()
    .append("line")
    .attr("class", "link")
    .style("stroke", "grey")
    .style("pointer-events", "none");
node = node.data(data.nodes)
    .enter()
    .append("g");
node.append("circle")
    .attr("class", "circle")
    .attr("r", function(d) { if(d.r){ return d.r; } else { return "18";} })
    .attr("fill", function(d) { if(d.color) { return d.color; } else { return "#24b8e3";} })
    .attr("stroke", function(d) { if(d.color) { return d.color; } else { return "#24b8e3";} });
var linkwrap = node.append("a")
    .attr("href", "3");
linkwrap.append("image")
    .attr("class", "srcico")
    .attr("height", "16px")
    .attr("width", "16px")
    .attr("xlink:href", function(d) { if(d.icon.length > 25) { return d.icon; } });


function tick() {
    var link = svg.selectAll("line");
    var edgepaths = svg.selectAll(".edgepath");
    var edgelabels = svg.selectAll(".edgelabel");


    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    svg.selectAll(".circle")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
    svg.selectAll(".srcico")
        .attr("x", function(d) { return d.x-5; })
        .attr("y", function(d) { return d.y-8; });
    svg.selectAll(".notecap")
        .attr("x", function(d) { return d.x; })
        .attr("y", function(d) { return d.y; });
}
}

在此之后,您所要做的就是抛出 AJAX 并获取数据,如下所示:

function graphUp(){
  $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: 'somelink',
        dataType: 'text',
        async: true,
        data: "", 
        success: function (data) {
           var freshdata = data;
           var newData= jQuery.parseJSON(freshdata);

                updateData(newData);

       },
        error: function (result) {
        }
}
)};

并将更新动画设置为看起来不错,如下所示:

var inter = setInterval(function() {
    graphUp();
    setTimeout(function() {
        force.linkDistance(20);
        force.start().alpha(0.01);
    }, 2000);
}, 5000);

非常感谢Gerardo找到了他对动画修复的答案 here

现在,我自然确信这不是最优雅的解决方案,因为我不是最优雅的开发人员,但它确实有效。该方法几乎会一直重新渲染完整数据,因此如果有人愿意参与其中并添加更新方法,请随意

关于javascript - D3.js 动画与 jQuery 更新相结合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41477135/

相关文章:

javascript - 如何改变v-select的颜色?

jquery - 如何使日期选择器始终清除文本框

jquery - HighCharts onclick this.point.name 未定义

javascript - Accordion 部分,单击图像以旋转图标

javascript - D3 分区 - 单击时显示下一个级别

javascript - 有没有办法让未链接的节点不以半径分布?

javascript - API 上的 jQuery 不会自动绑定(bind)

javascript - 如何在angular2中创建定时器

javascript - 将整个 svg 附加到 dom 元素会导致异常... "String contains an invalid character"代码 : "5"

javascript - 为什么我的 jQuery 只切换 HTML 中的第一个箭头?