D3.js:这是数据-DOM-绑定的良好做法吗?
D3.js: Is this good practise for data-DOM-binding?
我正在努力掌握 D3 的基础知识。我明白正确绑定是至关重要的。
所以我做了一个简单的网页,有更新,进入和退出操作。每次数据更改(修改、添加、删除)时,我都会调用一个函数,其中数据在更新、进入和退出方式中绑定到 svg-objects。
不知道我的方法好不好?
<html>
<head>
<style>
.drawarea { border-style: solid; }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data, drawArea;
function init(){
data = [{"px" : 25, "py" : 25, "s" : 5}, {"px" : 25, "py" : 50, "s" : 5}, {"px" : 25, "py" : 75, "s" : 10} ];
drawArea = d3.select("#drawareadiv").append("svg:svg")
.attr("class", "drawarea")
.attr("width", 500)
.attr("height", 250);
draw();
}
function draw(){
var domRects = drawArea.selectAll("rect");
// update
domRects
.data(data)
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
// enter
domRects
.data(data)
.enter()
.append("svg:rect")
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
// exit
domRects
.data(data)
.exit()
.remove();
}
function updateDataAndBinding(){
for(i=0; i<data.length; i++)
data[i].px += 10;
draw();
}
function enterDataAndBinding(){
var px = 25;
var py = 25 * (data.length+1);
var s = Math.floor(data.length/2)*5+5;
data.push({"px" : px, "py" : py, "s" : s});
draw();
}
function exitDataAndBinding(){
data.splice(data.length-1, 1);
draw();
}
</script>
</head>
<body onload="init()">
<div id="drawareadiv"></div>
<button onclick="updateDataAndBinding()">updateDataAndBinding</button>
<button onclick="enterDataAndBinding()">enterDataAndBinding</button>
<button onclick="exitDataAndBinding()">exitDataAndBinding</button>
</body>
</html>
我建议两件事:
不要一次又一次绑定数据。只做一次:
var domRects = drawArea.selectAll("rect").data(data);
因为这是D3v4.x,所以用merge
来处理"enter"和"update"的选择:
// enter + update
domRects.enter()
.append("svg:rect")
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; })
.merge(domRects)
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
这里是演示(点击"run code snippet"):
<style>
.drawarea { border-style: solid; }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data, drawArea;
function init(){
data = [{"px" : 25, "py" : 25, "s" : 5}, {"px" : 25, "py" : 50, "s" : 5}, {"px" : 25, "py" : 75, "s" : 10} ];
drawArea = d3.select("#drawareadiv").append("svg:svg")
.attr("class", "drawarea")
.attr("width", 500)
.attr("height", 200);
draw();
}
function draw(){
var domRects = drawArea.selectAll("rect").data(data);
// enter
domRects.enter()
.append("svg:rect")
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; })
.merge(domRects)
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
// exit
domRects.exit()
.remove();
}
function updateDataAndBinding(){
for(i=0; i<data.length; i++)
data[i].px += 10;
draw();
}
function enterDataAndBinding(){
var px = 25;
var py = 25 * (data.length+1);
var s = Math.floor(data.length/2)*5+5;
data.push({"px" : px, "py" : py, "s" : s});
draw();
}
function exitDataAndBinding(){
data.splice(data.length-1, 1);
draw();
}
</script>
</head>
<body onload="init()">
<div id="drawareadiv"></div>
<button onclick="updateDataAndBinding()">updateDataAndBinding</button>
<button onclick="enterDataAndBinding()">enterDataAndBinding</button>
<button onclick="exitDataAndBinding()">exitDataAndBinding</button>
</body>
除此之外,您的方法似乎是一个不错的(标准的)方法。
我正在努力掌握 D3 的基础知识。我明白正确绑定是至关重要的。
所以我做了一个简单的网页,有更新,进入和退出操作。每次数据更改(修改、添加、删除)时,我都会调用一个函数,其中数据在更新、进入和退出方式中绑定到 svg-objects。
不知道我的方法好不好?
<html>
<head>
<style>
.drawarea { border-style: solid; }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data, drawArea;
function init(){
data = [{"px" : 25, "py" : 25, "s" : 5}, {"px" : 25, "py" : 50, "s" : 5}, {"px" : 25, "py" : 75, "s" : 10} ];
drawArea = d3.select("#drawareadiv").append("svg:svg")
.attr("class", "drawarea")
.attr("width", 500)
.attr("height", 250);
draw();
}
function draw(){
var domRects = drawArea.selectAll("rect");
// update
domRects
.data(data)
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
// enter
domRects
.data(data)
.enter()
.append("svg:rect")
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
// exit
domRects
.data(data)
.exit()
.remove();
}
function updateDataAndBinding(){
for(i=0; i<data.length; i++)
data[i].px += 10;
draw();
}
function enterDataAndBinding(){
var px = 25;
var py = 25 * (data.length+1);
var s = Math.floor(data.length/2)*5+5;
data.push({"px" : px, "py" : py, "s" : s});
draw();
}
function exitDataAndBinding(){
data.splice(data.length-1, 1);
draw();
}
</script>
</head>
<body onload="init()">
<div id="drawareadiv"></div>
<button onclick="updateDataAndBinding()">updateDataAndBinding</button>
<button onclick="enterDataAndBinding()">enterDataAndBinding</button>
<button onclick="exitDataAndBinding()">exitDataAndBinding</button>
</body>
</html>
我建议两件事:
不要一次又一次绑定数据。只做一次:
var domRects = drawArea.selectAll("rect").data(data);
因为这是D3v4.x,所以用
merge
来处理"enter"和"update"的选择:// enter + update domRects.enter() .append("svg:rect") .attr("x", function(d) { return d.px; }) .attr("y", function(d) { return d.py; }) .attr("width", function(d) { return d.s; }) .attr("height", function(d) { return d.s; }) .merge(domRects) .attr("x", function(d) { return d.px; }) .attr("y", function(d) { return d.py; }) .attr("width", function(d) { return d.s; }) .attr("height", function(d) { return d.s; });
这里是演示(点击"run code snippet"):
<style>
.drawarea { border-style: solid; }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data, drawArea;
function init(){
data = [{"px" : 25, "py" : 25, "s" : 5}, {"px" : 25, "py" : 50, "s" : 5}, {"px" : 25, "py" : 75, "s" : 10} ];
drawArea = d3.select("#drawareadiv").append("svg:svg")
.attr("class", "drawarea")
.attr("width", 500)
.attr("height", 200);
draw();
}
function draw(){
var domRects = drawArea.selectAll("rect").data(data);
// enter
domRects.enter()
.append("svg:rect")
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; })
.merge(domRects)
.attr("x", function(d) { return d.px; })
.attr("y", function(d) { return d.py; })
.attr("width", function(d) { return d.s; })
.attr("height", function(d) { return d.s; });
// exit
domRects.exit()
.remove();
}
function updateDataAndBinding(){
for(i=0; i<data.length; i++)
data[i].px += 10;
draw();
}
function enterDataAndBinding(){
var px = 25;
var py = 25 * (data.length+1);
var s = Math.floor(data.length/2)*5+5;
data.push({"px" : px, "py" : py, "s" : s});
draw();
}
function exitDataAndBinding(){
data.splice(data.length-1, 1);
draw();
}
</script>
</head>
<body onload="init()">
<div id="drawareadiv"></div>
<button onclick="updateDataAndBinding()">updateDataAndBinding</button>
<button onclick="enterDataAndBinding()">enterDataAndBinding</button>
<button onclick="exitDataAndBinding()">exitDataAndBinding</button>
</body>
除此之外,您的方法似乎是一个不错的(标准的)方法。