Reputation: 35
I have a challenge, where i am trying to create 9 circles in each rectangle (4 in each corner, 4 on the sides and 1 in the middle) at the same time after immediately creating a rectangle. In my approach, 4 circles are created with a rectangle, which is not desired!
const svgId = 'campus_map';
const width = document.getElementById(svgId).viewBox.baseVal.width;
const height = document.getElementById(svgId).viewBox.baseVal.height;
let draw = Snap("#tiles");
let c = 0;
let size = Math.round(0.05 * width);
let circleSize = 25;
let circleColor = ["#ff0000", "#000000", "#00ffe1", "#0051ff"];
let svg = document.getElementById(svgId);
for (let i = 0; i <= width; i = i + size) {
for (let j = 0; j <= height; j = j + size) {
c += 1;
let rect = draw.rect(i, j, size, size);
let circle1 = draw.circle(i, j, circleSize);
let circle2 = draw.circle(i + (size / 2), j, circleSize);
let circle3 = draw.circle(i, j + (size / 2), circleSize);
let circle4 = draw.circle(i + (size / 2), j + (size / 2), circleSize);
rect.attr({
fill: "#d00bf3",
"fill-opacity": 0.2,
stroke: "#000",
"stroke-width": "1px",
id: "rect_" + c,
name: "rect" + c
});
circle1.attr({
fill: circleColor[0],
"fill-opacity": 1,
stroke: "#000",
"stroke-width": "1px",
id: "circle1_" + c,
name: "circle1_" + c
});
circle2.attr({
fill: circleColor[1],
"fill-opacity": 1,
stroke: "#000",
"stroke-width": "1px",
id: "circle2_" + c,
name: "circle2_" + c
});
circle3.attr({
fill: circleColor[2],
"fill-opacity": 1,
stroke: "#000",
"stroke-width": "1px",
id: "circle3_" + c,
name: "circle3_" + c
});
circle4.attr({
fill: circleColor[3],
"fill-opacity": 1,
stroke: "#000",
"stroke-width": "1px",
id: "circle4_" + c,
name: "circle4_" + c
});
}
}
<script src="https://unpkg.com/[email protected]"></script>
<svg viewBox="0 0 8204.08 6413.17" version="1.1" id="campus_map"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<g id="tiles"></g>
</svg>
Upvotes: 0
Views: 106
Reputation: 14565
Consider the use of pattern SVG
This is the easiest solution for your application.
You can easily change its content at any time.
You can also fill containers of any shape with a pattern and make them responsive.
Please look at the comments to understand how to position the pattern elements.
<svg width="100%" height="100%" version="1.1" viewBox="0 0 800 800"
xmlns="http://www.w3.org/2000/svg" >
<defs>
<pattern id="myPattern"
x="0" y="0" width="40" height="40"
patternUnits="userSpaceOnUse" >
<rect x="0" y="0" width="40" height="40" fill="#F6CEFD" stroke-width="0.5" stroke="black" />
<g stroke="none" >
<!-- Central circle -->
<circle cx="20" cy="20" r="3" fill="#0051FF"/>
<!-- Top mid circle -->
<circle cx="20" cy="0.5" r="3" fill="#000000"/>
<!-- Bottom mid circle -->
<circle cx="20" cy="40" r="3" fill="000"/>
<!-- left middle circle -->
<circle cx="0" cy="20" r="3" fill="#00FFE1"/>
<!-- right middle circle -->
<circle cx="40" cy="20" r="3" fill="#00FFE1"/>
<!-- upper left corner -->
<circle cx="0" cy="0" r="3" fill="#FF0000"/>
<!-- upper bottom corner -->
<circle cx="0" cy="40" r="3" fill="#FF0000"/>
<!-- top right corner -->
<circle cx="40" cy="0" r="3" fill="#FF0000"/>
<!-- bottom right corner -->
<circle cx="40" cy="40" r="3" fill="#FF0000"/>
</g>
</pattern>
</defs>
<rect x="0" y="0" width="100%" height="100%"
style="stroke: #000000; fill: url(#myPattern);" />
</svg>
An example of filling a Christmas tree with a pattern
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1" width="267" height="347" viewBox="0 0 267 347" >
<defs>
<pattern id="myPattern"
x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse" >
<rect x="0" y="0" width="40" height="40" fill="green" stroke-width="0.5" stroke="black" />
<g stroke="none" >
<!-- Central circle -->
<circle cx="20" cy="20" r="3" fill="#0051FF"/>
<!-- Top mid circle -->
<circle cx="20" cy="0.5" r="3" fill="gold"/>
<!-- Bottom mid circle -->
<circle cx="20" cy="40" r="3" fill="gold"/>
<!-- left middle circle -->
<circle cx="0" cy="20" r="3" fill="#00FFE1"/>
<!-- right middle circle -->
<circle cx="40" cy="20" r="3" fill="#00FFE1"/>
<!-- upper left corner -->
<circle cx="0" cy="0" r="3" fill="#FF0000"/>
<!-- upper bottom corner -->
<circle cx="0" cy="40" r="3" fill="#FF0000"/>
<!-- top right corner -->
<circle cx="40" cy="0" r="3" fill="#FF0000"/>
<!-- bottom right corner -->
<circle cx="40" cy="40" r="3" fill="#FF0000"/>
</g>
</pattern>
</defs>
<!-- filling a Christmas tree with a pattern -->
<path id="path4146" d="m119 262 28 0 0 86-28-2z" fill="brown" />
<path id="tree" fill="url(#myPattern)" d="M261 327 169 244c16 9 103 34 76 15-25-18-81-74-81-74 8 5 94 45 71 27-24-19-78-88-78-88 7 5 42 11 42 11-24-13-47-73-47-73 11 8 21 7 21 7C149 51 133 0 133 0c0 0-15 51-39 69 0 0 9 1 21-7 0 0-23 60-47 73 0 0 35-7 42-12 0 0-38 58-78 89-20 15 61-23 69-28 0 0-25 38-75 85-14 14 63-13 72-25 0 0-70 64-88 86-6 7 123-56 123-56 0 0 133 70 129 52z" id="path4" fill="#008000"/>
</svg>
Upvotes: 2
Reputation: 101868
In your loop, you only create four circles per tile. If you added five more your code would work. What is stopping you from doing that?
It sounds like you want the circles to be inside the square. To achieve that, you need to move the circles in by one circle radius.
Here's some modified code where I calculate that offset and use a loop to position the nine circles.
const svgId = 'campus_map';
const width = document.getElementById(svgId).viewBox.baseVal.width;
const height = document.getElementById(svgId).viewBox.baseVal.height;
let draw = Snap("#tiles");
let c = 0;
let size = Math.round(0.05 * width);
let circleSize = 25;
let circleColor = ["#ff0000", "#000000", "#00ffe1", "#0051ff"];
let svg = document.getElementById(svgId);
for (let i = 0; i <= width; i = i + size) {
for (let j = 0; j <= height; j = j + size) {
c += 1;
let rect = draw.rect(i, j, size, size);
rect.attr({
fill: "#d00bf3",
"fill-opacity": 0.2,
stroke: "#000",
"stroke-width": "1px",
id: "rect_" + c,
name: "rect" + c
});
// Now have another loop to create the nine circles.
// It sounds like you want to have the circle INSIDE the rectangle
// so you need to move the away from the rectangle corners by
// the radius (circleSize).
// The distance between the circles is the square size - two radiuses
// then divided in half
let circleSpacing = (size - circleSize * 2) / 2;
// Top left circle is one radius inside the top left square corner
let circleStartX = i + circleSize;
let circleStartY = j + circleSize;
for (let i2 = 0; i2 < 3; i2++) {
for (let j2 = 0; j2 < 3; j2++) {
c += 1;
let circle = draw.circle(circleStartX + i2 * circleSpacing, circleStartY + j2 * circleSpacing, circleSize);
circle.attr({
fill: circleColor[0],
"fill-opacity": 1,
stroke: "#000",
"stroke-width": "1px",
id: "circle1_" + c,
name: "circle1_" + c
});
}
}
}
}
<script src="https://unpkg.com/[email protected]"></script>
<svg viewBox="0 0 8204.08 6413.17" version="1.1" id="campus_map"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<g id="tiles"></g>
</svg>
Upvotes: 2