我一直在寻找一种使用D3和手绘铅笔的方法。这是可行的吗?我查看了mbostock网站上的不同示例,但找不到允许您在可缩放区域内手动绘制的任何内容。
答案 0 :(得分:5)
这可能会好起来......
(它是一个改进的粒子模式,重力,电荷和摩擦力设置为零)
;(function() {
var w = 900, h = 400, nodes = [], touch,
svg = d3.select("#vizcontainer").append("svg")
.attr("width", w)
.attr("height", h),
force = d3.layout.force()
.size([w, h])
.gravity(0)
.charge(0)
.friction(0),
outputDiv = d3.select("body").insert("div", "#vizcontainer").attr("id", "output").attr("class", "output"),
touchesDiv = d3.select("body").insert("div", "#output").attr("id", "touches")
.style("margin-right", "10px").attr("class", "output");
force.on("tick", function (e) {
outputDiv.text("alpha:\t" + d3.format(".3f")(force.alpha())
+ "\tnodes:\t" + force.nodes().length)
svg.selectAll("circle")
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
});
svg.on("mousemove", onMove);
svg.on("touchmove", onTouch);
svg.on("touchstart", onTouch);
function onMove() {
updateMethod.call(this)
}
function onTouch() {
d3.event.preventDefault();
d3.event.stopPropagation();
updateMethod.call(this)
}
function idiomatic() {
force.nodes(nodes);
return function () {
var pointM = d3.mouse(this), pointT = d3.touches(this),
point = pointT.length ? pointT[0] : pointM,
node = { x: point[0], y: point[1] };
nodes.push(node);
svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("r", 3)
.each((function (n) {
return function (d, i) {
var i = nodes.indexOf(n);
nodes.splice(i, 1)
}
})(node));
force.start();
}
} /*idiomatic*/
updateMethod = idiomatic();
})()

body, html {
width:100%;
height:100%;
}
#vizcontainer {
width: 100%;
height: 100%;
}
svg {
outline: 1px solid red;
width: 100%;
height: 100%;
}
.output {
pointer-events: none;
display: inline-block;
z-index: 1;
margin: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="vizcontainer"></div>
&#13;
试图接触Mark的解决方案......
var svg = d3.select('body')
.append('svg')
.attr('width', 1000)
.attr('height', 1000);
var color = d3.scale.category20();
var line = d3.svg.line();
var drawObj = {
isDown: false,
isTouched: false,
dataPoints: [],
currentPath: null,
color: 0
}
svg.on("mousedown", function () {
drawObj.isDown = true;
});
svg.on("mousemove", function () {
if (drawObj.isTouched) {
lift(); drawObj.isTouched = false
};
draw.call(this);
});
svg.on("touchmove", function () {
d3.event.preventDefault();
d3.event.stopPropagation();
drawObj.isDown = drawObj.isTouched = true;
draw.call(this);
});
svg.on("touchstart", function () {
if (drawObj.isTouched) {
lift(); drawObj.isTouched = false
};
})
function draw() {
if (drawObj.isDown) {
var pointM = d3.mouse(this), pointT = d3.touches(this),
point = pointT.length ? pointT[0] : pointM,
node = { x: point[0], y: point[1] };
drawObj.dataPoints.push(
[node.x, node.y]
);
if (!drawObj.currentPath) {
drawObj.currentPath = svg.append("path")
.attr("class", "currentPath")
.style("stroke-width", 1)
.style("stroke", color(drawObj.color))
.style("fill", "none");
}
drawObj.currentPath
.datum(drawObj.dataPoints)
.attr("d", line);
}
};
svg.on("mouseup", lift)
function lift () {
drawObj.isDown = false;
drawObj.currentPath && drawObj.currentPath.attr("class", "oldPath");
drawObj.dataPoints = [];
drawObj.currentPath = null;
if (++drawObj.color > 19) {
drawObj.color = 0;
}
}
&#13;
svg {
outline: 1px solid red;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
答案 1 :(得分:4)
我喜欢@ coolblue的解决方案,但这里有另一种选择。它使用一个路径元素来真正感觉像绘图:
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<script>
var svg = d3.select('body')
.append('svg')
.attr('width', 1000)
.attr('height', 1000);
var color = d3.scale.category20();
var line = d3.svg.line()
.interpolate("basis");
var drawObj = {
isDown: false,
dataPoints: [],
currentPath: null,
color: 0
}
svg.on("mousedown", function(){
drawObj.isDown = true;
});
svg.on("mousemove", function(){
if (drawObj.isDown){
drawObj.dataPoints.push(
[d3.event.x, d3.event.y]
);
if (!drawObj.currentPath){
drawObj.currentPath = svg.append("path")
.attr("class","currentPath")
.style("stroke-width", 1)
.style("stroke",color(drawObj.color))
.style("fill", "none");
}
drawObj.currentPath
.datum(drawObj.dataPoints)
.attr("d", line);
}
});
svg.on("mouseup", function(){
drawObj.isDown = false;
drawObj.currentPath.attr("class","oldPath");
drawObj.dataPoints = [];
drawObj.currentPath = null;
if (++drawObj.color > 19) {
drawObj.color = 0;
}
})
</script>
</body>
</html>
&#13;
Plunker here。