[英]How can I draw a continuous line using d3 without needing to click&drag the mouse, but rather just use the mouseover event?
我试图使用d3绘制一条连续的线而不点击鼠标。 目前我有这个d3代码,当我点击并移动时可以工作,但是当我只是进入应绘制线条的区域时,它不起作用。 我在这里提供了CodePen链接: https ://codepen.io/pwill2/pen/NLdJoL
的index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Freehand drawing</title>
<link rel="stylesheet" href="index.css">
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<svg id="canvas" width="500px" height="250px"></svg>
<script src="index.js"></script>
</body>
</html>
index.css
#canvas {
background: oldlace;
}
.swatch {
pointer-events: all;
}
.swatch.active {
stroke-width: 2px;
stroke: black;
}
.swatch {
cursor: pointer;
}
.btn {
pointer-events: all;
font-family: FontAwesome;
fill: #333;
font-size: 32px;
text-anchor: middle;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.btn:hover {
fill: black;
cursor: pointer;
}
.line {
fill: none;
stroke-width: 2px;
stroke-linejoin: round;
stroke-linecap: round;
}
index.js
(function() {
var SWATCH_D, active_color, active_line, canvas, drag, drawing_data, lines_layer, palette, redraw, render_line, swatches, trash_btn, ui;
SWATCH_D = 22;
render_line = d3.svg.line().x(function(d) {
return d[0];
}).y(function(d) {
return d[1];
}).interpolate('basis');
drawing_data = {
lines: [
{
color: "#000000",
points: []}
]
};
active_line = null;
active_color = "#000000";
canvas = d3.select('#canvas');
lines_layer = canvas.append('g');
drag = d3.behavior.drag();
drag.on('dragstart', function() {
active_line = {
points: [],
color: active_color
};
drawing_data.lines.push(active_line);
return redraw(active_line);
});
drag.on('drag', function() {
active_line.points.push(d3.mouse(this));
return redraw(active_line);
});
drag.on('dragend', function() {
if (active_line.points.length === 0) {
drawing_data.lines.pop();
}
active_line = null;
return console.log(drawing_data);
});
canvas.call(drag);
redraw = function(specific_line) {
var lines;
lines = lines_layer.selectAll('.line').data(drawing_data.lines);
lines.enter().append('path').attr({
"class": 'line',
stroke: function(d) {
return d.color;
}
}).each(function(d) {
return d.elem = d3.select(this);
});
if (specific_line != null) {
specific_line.elem.attr({
d: function(d) {
return render_line(d.points);
}
});
} else {
lines.attr({
d: function(d) {
return render_line(d.points);
}
});
}
return lines.exit().remove();
};
redraw();
}).call(this);
为什么不在画布上监听mousemove
事件而不是使用拖动,而是将点推送到路径绘制函数。
举个简单的例子:
var points = []; var canvas = d3.select("body") .append("canvas") .attr("height",500) .attr("width", 600) .on("mousemove", addPoint); var context = canvas.node().getContext("2d"); function addPoint() { points.push(d3.mouse(this)); draw(); } function draw() { context.clearRect(0,0,600,600); context.beginPath(); context.moveTo(...points[0]); points.forEach(function(d) { context.lineTo(...d); }) context.lineWidth = 1; context.stroke(); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
如果你需要在画布上单击鼠标的每个条目后绘制图形,你也可以在点击时分配mousemove监听器(鼠标移除下面的mousemove监听器,所以你可以绘制多行):
var points = []; var canvas = d3.select("body") .append("canvas") .attr("height",500) .attr("width", 600) .on("click", function() { points.push([]) d3.select(this).on("mousemove", addPoint); }) .on("mouseout", function() { d3.select(this).on("mousemove",null); }) var context = canvas.node().getContext("2d"); function addPoint() { points[points.length-1].push(d3.mouse(this)); draw(); } function draw() { context.clearRect(0,0,600,600); points.forEach(function(p) { context.beginPath(); context.moveTo(...p[0]); p.forEach(function(d) { context.lineTo(...d); }) context.lineWidth = 1; context.stroke(); }) }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
如果你想平滑曲线因为手抖动你可以使用d3.line和d3曲线绘制线条:
var points = []; var canvas = d3.select("body") .append("canvas") .attr("height",500) .attr("width", 600) .on("mousemove", addPoint); var context = canvas.node().getContext("2d"); var line = d3.line().context(context) .x(function(d) { return d[0]; }) .y(function(d) { return d[1]; }) .curve(d3.curveBasis); function addPoint() { points.push(d3.mouse(this)); draw(); } function draw() { context.clearRect(0,0,600,600) context.beginPath(); line(points); context.lineWidth = 1; context.stroke(); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
虽然你也可以过滤掉数组中的点以获得更平滑的东西(因为鼠标移动添加的点将根据鼠标速度非常接近地添加,使得平滑更难),或者使用不同的d3曲线:
var points = []; var canvas = d3.select("body") .append("canvas") .attr("height",500) .attr("width", 600) .on("mousemove", addPoint); var context = canvas.node().getContext("2d"); var line = d3.line().context(context) .x(function(d) { return d[0]; }) .y(function(d) { return d[1]; }) .curve(d3.curveBasis); function addPoint() { points.push(d3.mouse(this)); draw(); } function draw() { context.clearRect(0,0,600,600) context.beginPath(); line(points.filter(function(p,i) { if(i%8 == 0 || i == points.length-1) return p; })); context.lineWidth = 1; context.stroke(); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.