TonyC Posted November 3, 2021 Share Posted November 3, 2021 I hope this post is in the right place, I did not see an SVG forum. Some very basic SVG code: <!DOCTYPE html> <html> <body bgcolor="#000000#"> <svg width="800" height="400"> <rect width="200" height="200" style=" fill:rgb(0,0,0); stroke-width:2; stroke:rgb(255,0,255)" /> Sorry, your browser does not support inline SVG. </svg> </body> </html> Forgive "bgcolor", it's 2 am. 1. Why do the <svg> and <rect> tags both require width and height tags? 2 It looks like SVG is trying to create something like a beveled edge. There is what looks like 1 stroke on the top and left of the rectangle, and what looks like 2 strokes on the bottom and right of the rectangle. How do I get the same stroke on all four sides? Many thanks! Link to comment Share on other sites More sharing options...
Ingolme Posted November 3, 2021 Share Posted November 3, 2021 The width and height of the <svg> tag indicates how big your drawing area is. The width and height of the <rect> tag indicates how big the rectangle should be within the drawing area. It looks like your <rect> tag is missing the x and y attributes. You need to use them to specify where the top left corner of the rectangle should be within the drawing area. The reason that the line thicknesses vary is because the lines are not aligned with your screen's pixels, the problem is called aliasing. Setting the x and y coordinates will fix that because any integer value for x and y will align the rectangle with the pixels grid. Link to comment Share on other sites More sharing options...
TonyC Posted November 3, 2021 Author Share Posted November 3, 2021 I'm starting to think there's nothing you don't know. Thank you very much! Link to comment Share on other sites More sharing options...
TonyC Posted November 4, 2021 Author Share Posted November 4, 2021 Okay, my next task is to get the rectangle to appear in a random position. This will require some minor tweaks, like replacing absolute numbers in the <svg> tag with screen width and height, but it's working: <p id="demo"></p> <script> document.getElementById("demo").innerHTML = "<svg width = " + 1600 + " height = " + 800 + "> <rect x =" + (Math.random() * 100) + " y = " + (Math.random() * 100) + " height = " + 12 + " width = " + 12+ " rx = " + 2 + " style='fill:rgb(0,0,0); stroke-width:2; stroke:rgb(255,0,255)'/> </svg>"; </script> The problem is, the rectangle is appearing only within the small space that the browser is reserving for the paragraph. I want it to appear anywhere on the page. I tried using a <span> tag or a <div> tag immediately after the <body> tag and a </span> tag or a </div> tag immediately before the </body> tag, but that replaced the entire page with a small rectangle. Not what I had in mind. How would I get the rectangle to appear randomly on the page, in front of (or behind) the content? Thank you in advance! Link to comment Share on other sites More sharing options...
Ingolme Posted November 5, 2021 Share Posted November 5, 2021 The rectangle's position is always within the area reserved by the <svg> element, so if you want the <svg> image itself to appear somewhere random on the page then you will have to do that with CSS. If all you want is a rectangle, you don't even need SVG for that, any element with borders will work. SVG is useful if you want more complicated shapes. Here's a simple example to place a rectangle at a random location on the page: <!-- This goes in the head of the document --> <style> .rect { position: absolute; width: 12px; height: 12px; border-radius: 2px; /* rx */ border: 2px solid rgb(255,0,255); /* "Stroke" color and width */ background: #000; /* "Fill" color */ } </style> <!-- The body --> <div class="rect"></div> <script> var rect = document.querySelector(".rect"); rect.style.left = String( Math.floor(Math.random() * 101)) + "vw"; rect.style.top = String( Math.floor(Math.random() * 101)) + "vh"; </script> If you really want to use SVG instead, just replace the <div> with an <svg> picture. <!-- This goes in the head of the document --> <style> .rect { display: block; position: absolute; } </style> <!-- The body --> <svg class="rect" width="14" height="14"> <rect x="1" y="1" width="12" height="12" fill="#000" stroke="#F0F"></rect> </svg> <script> var rect = document.querySelector(".rect"); rect.style.left = String( Math.floor(Math.random() * 101)) + "vw"; rect.style.top = String( Math.floor(Math.random() * 101)) + "vh"; </script> Link to comment Share on other sites More sharing options...
TonyC Posted November 5, 2021 Author Share Posted November 5, 2021 Thank you so much for the effort you put into that reply. I'm very much looking forward to trying it. I'm curious, I tried placing a transparent canvas on the page, I thought that would work, but all I got was a blank page: <body> <canvas id="test"> <script> const canvas = document.getElementById('test'); const ctx = canvas.getContext('2d'); ctx.globalAlpha = 0.0; </script> ... </canvas> </body> I want to understand canvases better, any thoughts on why that did not work? Thanks again, you're amazing! Link to comment Share on other sites More sharing options...
Ingolme Posted November 5, 2021 Share Posted November 5, 2021 The canvas itself is transparent by default. The globalAlpha property determines the alpha of the elements that are going to be drawn next onto the canvas. If you set it to 0.0, nothing you draw will be visible. I'd recommend putting the <script> tags outside of the <canvas> element. There usually shouldn't be anything between the <canvas></canvas> tags. Link to comment Share on other sites More sharing options...
AARRGGHHH Posted November 21, 2021 Share Posted November 21, 2021 On 11/4/2021 at 8:04 PM, Ingolme said: If you really want to use SVG instead, just replace the <div> with an <svg> picture. <!-- This goes in the head of the document --> <style> .rect { display: block; position: absolute; } </style> <!-- The body --> <svg class="rect" width="14" height="14"> <rect x="1" y="1" width="12" height="12" fill="#000" stroke="#F0F"></rect> </svg> <script> var rect = document.querySelector(".rect"); rect.style.left = String( Math.floor(Math.random() * 101)) + "vw"; rect.style.top = String( Math.floor(Math.random() * 101)) + "vh"; </script> That worked fine (as you know!) thank you. What I'm trying to do here is create a lot of rectangles. I thought it would be a simple issue of iteration: <script> var rect = document.querySelector(".rect"); for (count = 1; count < 1001; count++) { rect.style.left = String( Math.floor(Math.random() * 101)) + "vw"; rect.style.top = String( Math.floor(Math.random() * 101)) + "vh"; } </script> But, as you've probably guessed, each rectangle is replacing the previous rectangle. So when the loop ends, there's only one rectangle. How do I get the rectangles to stay put as the loop runs? I tried using an array (I may have declared it wrong) as that just produced an error. <script> const rect = [document.querySelector(".rect")]; for (count = 1; count < 1001; count++) { rect.style.left = String( Math.floor(Math.random() * 101)) + "vw"; rect.style.top = String( Math.floor(Math.random() * 101)) + "vh"; } </script> // ERROR: "Uncaught TypeError: Cannot set properties of undefined (setting 'left')" I'm part new to drawing on the page and part rusty beyond description. This part of the code just seems like it should be easy. But I'm lost. I truly appreciate your help! Thanks Link to comment Share on other sites More sharing options...
Ingolme Posted November 21, 2021 Share Posted November 21, 2021 It's not that each rectangle is replacing the previous one, it's that you're changing the position of the same rectangle 1000 times over. In your second code example, the square brackets just create an array of size 1 with that single element in it. There's only one element on the page named <div class="rect"> right now, but even if there were more, document.querySelector() only selects the first one. To select multiple elements, you need to use document.querySelectorAll(). What you want, though, is not to select elements which already exist on the page, but to generate new ones. You can create copies of the first one by using the cloneNode() method. Here's how you would do that: <script> // Set the source rectangle's position let rect = document.querySelector(".rect"); rect.style.left = String( Math.floor(Math.random() * 101)) + "vw"; rect.style.top = String( Math.floor(Math.random() * 101)) + "vh"; // Make 1000 copies of the source rectangle for (let count = 0; count < 1000; count++) { // Create a copy. The "true" value meand that we want to copy the element's children as well. let copy = rect.cloneNode(true); // Set the position of the copied rectangle copy.style.left = String( Math.floor(Math.random() * 101)) + "vw"; copy.style.top = String( Math.floor(Math.random() * 101)) + "vh"; // Add the copy to the document as a child of the source rectangle's parent rect.parentNode.appendChild(copy); } </script> Link to comment Share on other sites More sharing options...
AARRGGHHH Posted November 21, 2021 Share Posted November 21, 2021 Once again, thank you very much! "querySelector" and "cloneNode" definitely were not covered in my college JavaScript class! :-) Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now