我正在使用d3绘制一些点。我想根据某些条件改变所有点的形状。联接看起来有点像这样:
var data=[{x:10,y:10}, {x:20, y:30}];
var shape = "rect";
...
var point = svg.selectAll(".point")
.data(data, function(d, idx) { return "row_" + idx + "_shape_" + shape;})
;
d3 enter()和exit()选项似乎不反映“shape”更改造成的任何更改。
答案 0 :(得分:2)
您需要注意,关键函数是根据选择计算的,this
作为SVG元素,然后是数据数组为this
的数据。
我想也许这就是你想要做的......
var data = [{
x: 10,
y: 10
}, {
x: 20,
y: 30
}];
var svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500);
function update(data, shape) {
var point = svg.selectAll(".point")
.data(data, function(d, idx) {
var key = "row_" + idx + "_shape_" + (Array.isArray(this) ? "Data: " + shape :
d3.select(this).attr("shape"));
alert(key);
return key;
});
alert("enter selection size: " + point.enter().size());
point.enter().append(shape)
.attr("class", "point")
.style("fill", "red")
.attr("shape", shape);
switch (shape) {
case "rect":
point.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
})
.attr("width", 5)
.attr("height", 5);
break;
case "circle":
point.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", 5);
break;
}
point.exit().remove();
}
update(data, "rect");
setTimeout(function() {
update(data, "circle");
}, 5000);

text {
font: bold 48px monospace;
}
.enter {
fill: green;
}
.update {
fill: #333;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script>
&#13;
在这里整理一下是一个更具可读性和惯用性的版本(包括解决文本元素的问题)......
var data = [{
x: 10,
y: 10,
}, {
x: 20,
y: 30,
}];
var svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500),
marker = Marker();
function update(data, shape) {
var point = svg.selectAll(".point")
.data(data, key("shape", shape)),
enter = point.enter().append("g")
.attr("class", "point")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"
})
.attr("shape", shape);
enter.append(shape)
.style("fill", "red")
.attr(marker.width[shape], 5)
.attr(marker.height[shape], 5);
enter.append("text")
.attr({
"class": "title",
dx: 10,
"text-anchor": "start"
})
.text(shape);
point.exit().remove();
}
update(data, "rect");
setTimeout(function() {
update(data, "circle");
}, 2000);
function Marker() {
return {
width: {
rect: "width",
circle: "r"
},
height: {
rect: "height",
circle: "r"
},
shape: function(d) {
return d.shape
},
};
}
function key(attr, value) {
//join data and elements where value of attr is value
function _phase(that) {
return Array.isArray(that) ? "data" : "element";
}
function _Type(that) {
return {
data: value,
get element() {
return d3.select(that).attr(attr)
}
}
}
return function(d, i, j) {
var _value = _Type(this)
return i + "_" + _value[_phase(this)];
};
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
var data = [{
x: 10,
y: 10,
}, {
x: 20,
y: 30,
}];
var svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 500),
marker = Marker();
function update(data, shape) {
//data-driven approach
data.forEach(function(d, i) {
d.shape = shape[i]
});
var log = [],
point = svg.selectAll(".point")
.data(data, key({
shape: marker.shape,
transform: marker.transform
}, log)),
//UPDATE
update = point.classed("update", true),
updateSize = update.size();
update.selectAll("text").transition().duration(1000).style("fill", "#ccc");
update.selectAll(".shape").transition().duration(1000).style("fill", "#ccc")
//ENTER
var enter = point.enter().append("g")
.classed("point enter", true)
.attr("transform", marker.dock)
.attr("shape", marker.shape),
//UPDATE+ENTER
// ... not required on this occasion
updateAndEnter = point.classed("update-enter", true);
//EXIT
var exit = point.exit().classed("exit", true);
exit.selectAll("text").transition().duration(1000).style("fill", "red");
exit.selectAll(".shape").transition().duration(1000).style("fill", "red");
exit.transition().delay(1000.).duration(1000)
.attr("transform", marker.dock)
.remove();
//ADJUSTMENTS
enter.each(function(d) {
//append the specified shape for each data element
//wrap in each so that attr can be a function of the data
d3.select(this).append(marker.shape(d))
.style("fill", "green")
.classed("shape", true)
.attr(marker.width[marker.shape(d)], 5)
.attr(marker.height[marker.shape(d)], 5)
});
enter.append("text")
.attr({
"class": "title",
dx: 10,
"text-anchor": "start"
})
.text(marker.shape)
.style("fill", "green")
.style("opacity", 1);
enter.transition().delay(1000).duration(2000)
.attr("transform", marker.transform);
}
data = generateData(40, 10)
update(data, data.map(function(d, i) {
return ["rect", "circle"][Math.round(Math.random())]
}));
setInterval(function() {
update(data, data.map(function(d, i) {
return ["rect", "circle"][Math.round(Math.random())]
}));
}, 5000);
function generateData(n, p) {
var values = [];
for (var i = 0; i < n; i++) {
values.push({
x: (i + 1) * p,
y: (i + 1) * p
})
}
return values;
};
function Marker() {
return {
x: {
rect: "x",
circle: "cx"
},
y: {
rect: "y",
circle: "cy"
},
width: {
rect: "width",
circle: "r"
},
height: {
rect: "height",
circle: "r"
},
shape: function(d) {
return d.shape
},
transform: function(d) {
return "translate(" + f(d.x) + "," + f(d.y) + ")"
},
dock: function(d) {
return "translate(" + (d.x + 800) + "," + (d.y + 100) + ")"
}
};
function f(x) {
return d3.format(".0f")(x)
}
}
function key(attr, value, log) {
//join data and elements where value of attr is value
function _phase(that) {
return Array.isArray(that) ? "data" : "element";
}
function _Key(that) {
if (plural) {
return {
data: function(d, i, j) {
var a, key = "";
for (a in attr) {
key += (typeof attr[a] === "function" ? attr[a](d, i, j) : attr[a]);
}
return key;
},
element: function() {
var a, key = "";
for (a in attr) {
key += d3.select(that).attr(a);
}
return key;
}
}
} else {
return {
data: function(d, i, j) {
return typeof value === "function" ? value(d, i, j) : value;
},
element: function() {
return d3.select(that).attr(attr)
}
}
}
}
var plural = typeof attr === "object";
if (plural && arguments.length === 2) log = value;
return function(d, i, j) {
var key = _Key(this)[_phase(this)](d, i, j);
if (log) log.push(i + "_" + _phase(this) + "_" + key);
return key;
};
}
&#13;
text {
font: bold 12px monospace;
fill: black;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;