D3 Javascript - 这些行不会移动

时间:2016-12-11 18:54:55

标签: javascript html animation d3.js

处理D3项目,并成功动画了一些随机移动的圆圈。我想在它们和某些点(我已经完成)之间绘制一条线,但线条似乎没有用圆圈更新!

我的印象是,由于D3的数据绑定,UI总是会反映数据,所以我需要做的就是修改底层数据!

请参阅下面的问题(我为长代码帖子道歉)。

function play() {
	run = !run;
}

var run = false;

var canvas = d3.select('html')
		.append('svg')
		.attr('width', screen.width)
		.attr('height', screen.height);

var text = canvas.append("svg:text")
		.attr("x", 300)
		.attr("y", 100)
		.attr('id', 'fps');
	
var start = Date.now(),
	frames = 0;

function agent(_x, _y, _vx, _vy, _color) {
	this.x = _x;
	this.y = _y;
	this.vx = _vx;
	this.vy = _vy;
	this.color = _color;
	this.lines = [];
}

function line(_x1, _y1, _x2, _y2) {
	this.x1 = _x1;
	this.y1 = _y1;
	this.x2 = _x2;
	this.y2 = _y2;
}

var data = d3.range(3).map(function() {
	return new agent(
		(Math.random()-0.5)*5,
		(Math.random()-0.5)*5,
		0,
		0,
		'rgb(255, 0, 213)');
});

data.forEach(function(d) {
	d.lines.push(new line(d.x, d.y, 0, 0));
});

var x = d3.scaleLinear()
	.domain([-5, 5])
	.range([0, screen.width/3]);

var y = d3.scaleLinear()
	.domain([-5, 5])
	.range([0, screen.height/3]);

var circles = canvas.selectAll('circle')
		.data(data)
		.enter().append('circle')
		.attr('cx', function(d) {
			return x(d.x);
		})
		.attr('cy', function(d) {
			return y(d.y);
		})
		.attr('r', 5)
		.attr('fill', function(d) {
			return d.color;
		});

var lines = canvas.selectAll('line')
		.data(data)
		.enter().append('line')
		.attr('x1', function(d) {
			return x(d.lines[0].x1);
		})
		.attr('y1', function(d) {
			return y(d.lines[0].y1);
		})
		.attr('x2', function(d) {
			return x(d.lines[0].x2);
		})
		.attr('y2', function(d) {
			return y(d.lines[0].y2);
		})
		.attr('stroke', 'white')
		.attr('stroke-width', 1);

//initializes circles at center to begin
render();

d3.timer(function() {
	//Update FPS
	var now = Date.now(), duration = now - start;
	text.text(~~(++frames * 1000 / duration));
	if (duration >= 1000) frames = 0, start = now;

	if (run) {
		rendezvous();
		render();
	}
});

function render() {
	circles.attr('transform', function(d) {
		return 'translate(' + d.x + ',' + d.y + ')';
	}).attr('fill', function(d) {
		return d.color;
	});
    //Transform the line here???
}


function rendezvous() {
	data.forEach(function(d) {
		d.vx += (Math.random()-0.5)*0.5;
		d.vy += (Math.random()-0.5)*0.5;
		d.x += d.vx;
		d.y += d.vy;

		d.lines[0].x1 = d.x;
		d.lines[0].y1 = d.y;
		d.lines[0].x2 = 0;
		d.lines[0].y2 = 0;
	});
}
body {
	background-color: rgb(39, 40, 34);
	position: absolute;
}

h1 {
	font-family: Helvetica;
	color: white;
}

#fps {
	font-family: Helvetica;
	fill: white;
}
<!DOCTYPE html>
<meta charset="utf-8">
<html>
	<head>
		<link rel="stylesheet" type="text/css" href="styles.css">
		<script src="https://d3js.org/d3.v4.js"></script>
	</head>
	<body id = "body">
		<h1>Swarm Demo: </h1>
		<button type="button"onclick = "play();">Play/Pause</button>
	</body>
	<script src="js/rendezvous.js" type="text/javascript"></script>
</html>

1 个答案:

答案 0 :(得分:1)

这不是最佳解决方案,但鉴于您现在的代码,这是可能的解决方案:

if (run) {
    lines.attr('x1', function(d) {
            return +(d3.select(this).attr("x1")) + d.vx;
        })
        .attr('y1', function(d) {
            return +(d3.select(this).attr("y1")) + d.vy;
        })
}

以下是演示:

&#13;
&#13;
function play() {
	run = !run;
}

var run = false;

var canvas = d3.select('html')
		.append('svg')
		.attr('width', screen.width)
		.attr('height', screen.height);

var text = canvas.append("svg:text")
		.attr("x", 300)
		.attr("y", 100)
		.attr('id', 'fps');
	
var start = Date.now(),
	frames = 0;

function agent(_x, _y, _vx, _vy, _color) {
	this.x = _x;
	this.y = _y;
	this.vx = _vx;
	this.vy = _vy;
	this.color = _color;
	this.lines = [];
}

function line(_x1, _y1, _x2, _y2) {
	this.x1 = _x1;
	this.y1 = _y1;
	this.x2 = _x2;
	this.y2 = _y2;
}

var data = d3.range(3).map(function() {
	return new agent(
		(Math.random()-0.5)*5,
		(Math.random()-0.5)*5,
		0,
		0,
		'rgb(255, 0, 213)');
});

data.forEach(function(d) {
	d.lines.push(new line(d.x, d.y, 0, 0));
});

var x = d3.scaleLinear()
	.domain([-5, 5])
	.range([0, screen.width/3]);

var y = d3.scaleLinear()
	.domain([-5, 5])
	.range([0, screen.height/3]);

var circles = canvas.selectAll('circle')
		.data(data)
		.enter().append('circle')
		.attr('cx', function(d) {
			return x(d.x);
		})
		.attr('cy', function(d) {
			return y(d.y);
		})
		.attr('r', 5)
		.attr('fill', function(d) {
			return d.color;
		});

var lines = canvas.selectAll('line')
		.data(data)
		.enter().append('line')
		.attr('x1', function(d) {
			return x(d.lines[0].x1);
		})
		.attr('y1', function(d) {
			return y(d.lines[0].y1);
		})
		.attr('x2', function(d) {
			return x(d.lines[0].x2);
		})
		.attr('y2', function(d) {
			return y(d.lines[0].y2);
		})
		.attr('stroke', 'white')
		.attr('stroke-width', 1);

//initializes circles at center to begin
render();

d3.timer(function() {
	//Update FPS
	var now = Date.now(), duration = now - start;
	text.text(~~(++frames * 1000 / duration));
	if (duration >= 1000) frames = 0, start = now;

	if (run) {
		rendezvous();
		render();
	}
});

function render() {
	circles.attr('transform', function(d) {
		return 'translate(' + d.x + ',' + d.y + ')';
	}).attr('fill', function(d) {
		return d.color;
	});
    //Transform the line here???
  	if(run){
  lines.attr('x1', function(d) {
			return +(d3.select(this).attr("x1")) + d.vx;
		})
		.attr('y1', function(d) {
			return +(d3.select(this).attr("y1")) + d.vy;
		})
	}
}


function rendezvous() {
	data.forEach(function(d) {
		d.vx += (Math.random()-0.5)*0.5;
		d.vy += (Math.random()-0.5)*0.5;
		d.x += d.vx;
		d.y += d.vy;

		d.lines[0].x1 = d.x;
		d.lines[0].y1 = d.y;
		d.lines[0].x2 = 0;
		d.lines[0].y2 = 0;
	});
}
&#13;
body {
	background-color: rgb(39, 40, 34);
	position: absolute;
}

h1 {
	font-family: Helvetica;
	color: white;
}

#fps {
	font-family: Helvetica;
	fill: white;
}
&#13;
<!DOCTYPE html>
<meta charset="utf-8">
<html>
	<head>
		<link rel="stylesheet" type="text/css" href="styles.css">
		<script src="https://d3js.org/d3.v4.js"></script>
	</head>
	<body id = "body">
		<h1>Swarm Demo: </h1>
		<button type="button"onclick = "play();">Play/Pause</button>
	</body>
	<script src="js/rendezvous.js" type="text/javascript"></script>
</html>
&#13;
&#13;
&#13;