Reputation:
I have to create 30 triangle in random position; for the shape I am using the d3.symbolTriangle and I can set the dimension of it through attr("d", triangle.size(dim), that should be the area of the triangle. The problem is that some triangle are not totally inside the svg container, that has some borders, and some parts of these triangles are outside (see in the picture). How can I force these inside the container, like with a margine of x pixel? This is my code:
var width = window.innerWidth;
var height = window.innerHeight;
var triangle = d3.symbol()
.type(d3.symbolTriangle);
function drawTriangles(number) {
for(var i=0;i<number;i++){
var dim = Math.random()*300;
console.log("Path: "+i+", dim: "+dim);
svg.append("path")
.attr("d", triangle.size(dim))
.attr("transform", function(d) { return "translate(" + Math.random()*width + "," + Math.random()*height + ")"; })
.attr("fill", "rgb("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+")")
.attr("opacity", 2)
.attr("class", "path"+i);
}
}
This is the fiddle: https://jsfiddle.net/jjr3kqao/
You can see the blue triangle that is not inside the container:
Upvotes: 0
Views: 1470
Reputation: 3324
You can easily use the element bounding box size when you set it's translate value.
It's strange, but for triangles to fully be inside svg, using bbox height does not work. Shapes width are a couple of pixels larger than their heights and using that value in computations works.
var width = 250;
var height = 250;
var number = 30;
var borderSize = 1;
var body = d3.select("body");
var triangle = d3.symbol()
.type(d3.symbolTriangle);
var svg = body.append("svg")
.attr("width", width)
.attr("height", height)
.style("border", "1px solid black");
function drawTriangles(number) {
for (var i = 0; i < number; i++) {
var dim = Math.random() * 300;
svg.append("path")
.attr("d", triangle.size(dim))
.attr("transform", function (d) {
var boundingBox = this.getBBox();
var elementWidth = Math.ceil(boundingBox.width);
var randomXOffset = Math.random() * (width - elementWidth - 2 * borderSize) + elementWidth/2 + borderSize;
var randomYOffset = Math.random() * (height - elementWidth - 2 * borderSize) + elementWidth/2 + borderSize;
return "translate(" + randomXOffset + "," + randomYOffset + ")";
})
.attr("fill", "rgb(" + parseInt(Math.random() * 255) + "," + parseInt(Math.random() * 255) + "," + parseInt(Math.random() * 255) + ")")
.attr("opacity", 2)
.attr("class", "path" + i);
}
}
drawTriangles(number);
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
</body>
Upvotes: 3
Reputation: 102219
If you set the desired margin:
var margin = 20;
You can avoid the triangles having their center positioned within that margin:
.attr("transform", function(d)
{ return "translate(" + (margin + Math.random()*(width - margin))
+ "," + (margin + Math.random()*(height - margin)) + ")";
})
Have in mind that this doesn't take in consideration the fact that the triangles have different sizes: it sets the same margin for everyone.
Here is the fiddle: https://jsfiddle.net/7qkqtwmu/
Upvotes: 1