我有以下d3js代码,我正在尝试做两件事 - 这个问题只是关于第一个:
1)我想在绿点之间画一条绿色虚线。
2)最后,我想要一个仅以红色路径开头的动画,当你点击文本时,它会将红色路径转换为绿色路径(排序为"沉没")
对任何一方的建议都会很棒!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Labels removed</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<p>Click me to move the line[not working yet]</p>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
var padding = 30;
//Static dataset
var dataset = [
[2,13],[5, 21], [7,22],[8,28],[10, 30], [12, 34], [13,36],[16,42],[17, 44]
];
var dataset2 = [
[12, 28], [13,26],[16,19],[17, 13]
];
//Create scale functions
var xScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - padding, padding]);
// var rScale = d3.scale.linear()
// .domain([0, d3.max(dataset, function(d) { return d[1]; })])
// .range([2, 5]);
//Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5);
//Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create circles
svg.append("g")
.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return 5;})
.attr("fill", function(d){
if (d[0] > 11) {return "red";}
else return "black";
});
svg.append("g")
.selectAll("circle")
.data(dataset2)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return 5;
})
.attr("fill", "green");
//Create X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
//Create Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
//Create dividing line
svg.append("line")
.attr("x1", xScale(dataset[0][0]))
.attr("y1", yScale(dataset[0][1]))
.attr("x2", xScale(dataset[4][0]))
.attr("y2", yScale(dataset[4][1]))
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,5");
svg.append("line")
.attr("x1", xScale(dataset[4][0]))
.attr("y1", yScale(dataset[4][1]))
.attr("x2", xScale(dataset[8][0]))
.attr("y2", yScale(dataset[8][1]))
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,5");
svg.append("line")
.attr("x1", xScale(11))
.attr("y1", 0)
.attr("x2", xScale(11))
.attr("y2", h-padding)
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,5");
d3.select("p")
.on("click", function() {
//code for moving line goes here
});
</script>
</body>
</html>
答案 0 :(得分:2)
连接绿点的最简单方法是path generator:
var line = d3.svg.line()
.x(function(d) { return xScale(d[0]); })
.y(function(d) { return yScale(d[1]); });
greenG
.append("path")
.attr("d", line(dataset2))
.style("fill", "none")
.style("stroke", "green")
.style("stroke-dasharray", "5,5");
你的下降线有点复杂。这是一个实现:
// create an array of "interpolaters" for each point to be moved
// from the greenSet to the redSet
var interpolaters = [];
greenSet.forEach(function(d,i){
interpolaters.push({
x: d3.interpolate(xScale(redSet[i][0]), xScale(d[0])),
y: d3.interpolate(yScale(redSet[i][1]), yScale(d[1]))
})
});
// set up a path generator line function to be used
var fallLine = d3.svg.line()
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; });
// g to hold our falling line and points
var fallingG = svg.append("g");
// this path is our line
fallingPath = fallingG
.append("path")
.style("fill", "none")
.style("stroke", "steelblue")
.style("stroke-dasharray", "5,5")
// set up the transition
.transition()
// delay it 1s
.delay(1000)
// it'll last 3s
.duration(3000)
.ease('linear')
// custom tween, that'll redraw the line on each animation
.tween("fallLine", function(d) {
var path = d3.select(this);
return function(t) {
var lineData = [];
// loop our interpolaters to get current line positions
interpolaters.forEach(function(i){
lineData.push([i.x(t),i.y(t)]);
});
path.attr("d", fallLine(lineData));
};
});
// similar code for our circles
fallingG
.selectAll("circle")
.data(interpolaters)
.enter()
.append("circle")
.style("fill","steelblue")
.attr("r", 5)
.transition()
.delay(1000)
.duration(3000)
.ease('linear')
// here we can use attrTween instead of a custom tween
.attrTween("cx", function(d){
return d.x;
})
.attrTween("cy", function(d){
return d.y;
});
完整的工作代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>D3: Labels removed</title>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style type="text/css">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<p>Click me to move the line[not working yet]</p>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
var padding = 30;
//Static dataset
var blackSet = [
[2, 13],
[5, 21],
[7, 22],
[8, 28],
[10, 30]
];
var redSet = [
[12, 34],
[13, 36],
[16, 42],
[17, 44]
];
var greenSet = [
[12, 28],
[13, 26],
[16, 19],
[17, 13]
];
//Create scale functions
var xScale = d3.scale.linear()
.domain([0, d3.max(redSet, function(d) {
return d[0];
})])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(redSet, function(d) {
return d[1];
})])
.range([h - padding, padding]);
// var rScale = d3.scale.linear()
// .domain([0, d3.max(dataset, function(d) { return d[1]; })])
// .range([2, 5]);
//Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5);
//Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create circles
svg.append("g")
.selectAll("circle")
.data(blackSet)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return 5;
})
.attr("fill", "black");
svg.append("g")
.selectAll("circle")
.data(redSet)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return 5;
})
.attr("fill", "red");
var greenG = svg.append("g");
greenG
.selectAll("circle")
.data(greenSet)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.attr("r", function(d) {
return 5;
})
.attr("fill", "green");
var line = d3.svg.line()
.x(function(d) { return xScale(d[0]); })
.y(function(d) { return yScale(d[1]); });
greenG
.append("path")
.attr("d", line(greenSet))
.style("fill", "none")
.style("stroke", "green")
.style("stroke-dasharray", "5,5");
//Create X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
//Create Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
//Create dividing line
svg.append("line")
.attr("x1", xScale(blackSet[0][0]))
.attr("y1", yScale(blackSet[0][1]))
.attr("x2", xScale(blackSet[4][0]))
.attr("y2", yScale(blackSet[4][1]))
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,5");
svg.append("line")
.attr("x1", xScale(redSet[0][0]))
.attr("y1", yScale(redSet[0][1]))
.attr("x2", xScale(redSet[3][0]))
.attr("y2", yScale(redSet[3][1]))
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,5");
svg.append("line")
.attr("x1", xScale(11))
.attr("y1", 0)
.attr("x2", xScale(11))
.attr("y2", h - padding)
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-dasharray", "5,5");
d3.select("p")
.on("click", function() {
//code for moving line goes here
});
var interpolaters = [];
greenSet.forEach(function(d,i){
interpolaters.push({
x: d3.interpolate(xScale(redSet[i][0]), xScale(d[0])),
y: d3.interpolate(yScale(redSet[i][1]), yScale(d[1]))
})
});
var fallLine = d3.svg.line()
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; });
var fallingG = svg.append("g");
fallingPath = fallingG
.append("path")
.style("fill", "none")
.style("stroke", "steelblue")
.style("stroke-dasharray", "5,5")
.transition()
.delay(1000)
.duration(3000)
.ease('linear')
.tween("fallLine", function(d) {
var path = d3.select(this);
return function(t) {
var lineData = [];
interpolaters.forEach(function(i){
lineData.push([i.x(t),i.y(t)]);
});
path.attr("d", fallLine(lineData));
};
});
fallingG
.selectAll("circle")
.data(interpolaters)
.enter()
.append("circle")
.style("fill","steelblue")
.attr("r", 5)
.transition()
.delay(1000)
.duration(3000)
.ease('linear')
.attrTween("cx", function(d){
return d.x;
})
.attrTween("cy", function(d){
return d.y;
});
</script>
</body>
</html>
&#13;