我有2个简单的区域图,我使用D3.js创建了数据&下面的代码 - 我们称之为Graph A
& Graph B
。我想用它们根据它们的交叉方式创建3个新的路径/多边形。
Path 1
= Graph A
- Graph B
Path 2
= Graph B
- Graph A
Path 3
= Graph B
- Path 2
或Graph A
和Graph B
交叉点大多数可视化编辑器允许您执行这些布尔操作,请参阅:https://en.wikipedia.org/wiki/Boolean_operations_on_polygons
是否可以在D3.js中执行此操作?
jsfiddle:https://jsfiddle.net/jvf1utmx/
图表定义:
// data
var dataA = [
{ x: 0, y: 100, },
{ x: 100, y: 150, },
{ x: 200, y: 350, },
{ x: 300, y: 200, },
];
var dataB = [
{ x: 0, y: 200, },
{ x: 100, y: 100, },
{ x: 200, y: 250, },
{ x: 300, y: 150, },
];
// Graph shapes
var graphA = svg.append("path")
.datum(dataA)
.attr("class", "area")
.attr("d", area)
.style({fill: '#bbbb00', opacity: 0.8});
var graphB = svg.append("path")
.datum(dataB)
.attr("class", "area")
.attr("d", area)
.style({fill: '#666666', opacity: 0.8});
我尝试剪辑路径:
// Clipping attempts
var graphBClip = svg.append("clipPath")
.attr('id','graphBClip')
graphBClip.append(graphB);
graphA.attr("clip-path","url(#graphBClip)");
答案 0 :(得分:3)
作为我评论的后续行动;我刚刚尝试了我链接的GreinerHormann库。它与d3
非常相似(它以相同的方式输入对象数组)。
以下是A - B
和B - A
的简短示例:
<!DOCTYPE html>
<html>
<head>
<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>
<script src="https://rawgit.com/w8r/GreinerHormann/master/dist/greiner-hormann.min.js"></script>
</head>
<body>
<script>
// data
var dataA = [{
x: 0,
y: 100,
}, {
x: 100,
y: 150,
}, {
x: 200,
y: 350,
}, {
x: 300,
y: 200,
}, ];
var dataB = [{
x: 0,
y: 200,
}, {
x: 100,
y: 100,
}, {
x: 200,
y: 250,
}];
var area = d3.svg.line()
.x(function(d){
return d.x;
})
.y(function(d){
return d.y;
});
var svg = d3.select('body')
.append('svg')
.attr('width', 500)
.attr('height', 500);
// Graph shapes
var graphA = svg.append("path")
.datum(dataA)
.attr("class", "area")
.attr("d", area)
.style({
fill: 'none'
});
var graphB = svg.append("path")
.datum(dataB)
.attr("class", "area")
.attr("d", area)
.style({
fill: 'none'
});
var AminusB = greinerHormann.diff(dataA, dataB);
var BminusA = greinerHormann.diff(dataB, dataA);
// Graph shapes
AminusB.forEach(function(d){
svg.append("path")
.datum(d)
.attr("class", "area")
.attr("d", area)
.style({
fill: 'steelblue',
opacity: 0.8
});
});
// Graph shapes
BminusA.forEach(function(d){
svg.append("path")
.datum(d)
.attr("class", "area")
.attr("d", area)
.style({
fill: 'orange',
opacity: 0.8
});
});
</script>
</body>
</html>
&#13;
答案 1 :(得分:1)
jsclipper(sourceforge.net/projects/jsclipper)解决方案
// Accepts array or coordinate arrays [[{X:,Y:}]] - note X & Y must be upper case, d3.js requires lowercase
function boolean2D(subj_paths, clip_paths, clip_type) {
var ct;
switch (clip_type) {
case "union":
ct = ClipperLib.ClipType.ctUnion;
break;
case "difference":
ct = ClipperLib.ClipType.ctDifference;
break;
case "intersection":
ct = ClipperLib.ClipType.ctIntersection;
break;
case "exclusion":
ct = ClipperLib.ClipType.ctXor;
break;
}
var cpr = new ClipperLib.Clipper();
cpr.AddPaths(subj_paths, ClipperLib.PolyType.ptSubject, true); // true means closed path
cpr.AddPaths(clip_paths, ClipperLib.PolyType.ptClip, true);
var solution_paths = new ClipperLib.Paths();
var succeeded = cpr.Execute(ct, solution_paths, ClipperLib.PolyFillType.pftNonZero, ClipperLib.PolyFillType.pftNonZero);
return solution_paths //produces array of paths to plug into d3.js
}
aXY = boolean2D(x,y,"difference");
// convert XY to lowercase
axy = [];
aXY.forEach(function(d) {
b = []
d.forEach(function(c) {
b.push({x:c.X, y:c.Y});
});
axy.push(b);
});
//d3 output
var svg = d3.select('#chart').append('svg')
.attr('width', 500)
.attr('height', 500)
.style('background', '#C9D7D6');
axy.forEach(function(d){
svg.append("path")
.attr("d", lineFunction(d))
.style({
fill: 'orange',
opacity: 0.8
});
});