102

I want to create a rectangle inside an HTML page, then write some text on that rectangle. I also need that text to be a hyperlink. This is what I did but it is not working:

    <!DOCTYPE html>
<html>
<body>

<script>

    var svg   = document.documentElement;
    var svgNS = svg.namespaceURI;

    var rect = document.createElementNS(svgNS,'rect');
    rect.setAttribute('x',5);
    rect.setAttribute('y',5);
    rect.setAttribute('width',500);
    rect.setAttribute('height',500);
    rect.setAttribute('fill','#95B3D7');
    svg.appendChild(rect);
    document.body.appendChild(svg);

    var h=document.createElement('a');
    var t=document.createTextNode('Hello World');
    h.appendChild(t);
    document.body.appendChild(h);


</script>

</body>
</html>

Can you help please? Thanks.

1

4 Answers 4

151

Change

var svg   = document.documentElement;

to

var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");

so that you create a SVG element.

For the link to be an hyperlink, simply add a href attribute :

h.setAttributeNS(null, 'href', 'http://www.google.com');

Demonstration

Sign up to request clarification or add additional context in comments.

2 Comments

Ok I will. The text works, but I want to change its position. I want it to be displayed on the rectangle like in the middle of the rect for example.
Note that the link is an html anchor tag, if you want it to be inside the svg you need to create an <svg:text> element (in the svg namespace), and an <svg:a> element, and then append these to the svg. See e.g stackoverflow.com/questions/19132443/….
60

To facilitate svg editing you can use an intermediate function:

function getNode(n, v) {
  n = document.createElementNS("http://www.w3.org/2000/svg", n);
  for (var p in v)
    n.setAttributeNS(null, p, v[p]);
  return n
}

Now you can write:

svg.appendChild( getNode('rect', { width:200, height:20, fill:'#ff0000' }) );

Example (with an improved getNode function allowing camelcase for property with dash, eg strokeWidth > stroke-width):

function getNode(n, v) {
  n = document.createElementNS("http://www.w3.org/2000/svg", n);
  for (var p in v)
    n.setAttributeNS(null, p.replace(/[A-Z]/g, function(m, p, o, s) { return "-" + m.toLowerCase(); }), v[p]);
  return n
}

var svg = getNode("svg");
document.body.appendChild(svg);

var r = getNode('rect', { x: 10, y: 10, width: 100, height: 20, fill:'#ff00ff' });
svg.appendChild(r);

var r = getNode('rect', { x: 20, y: 40, width: 100, height: 40, rx: 8, ry: 8, fill: 'pink', stroke:'purple', strokeWidth:7 });
svg.appendChild(r);

3 Comments

Notice that the "camelcase to dash feature" screws things up for you if you try to set the attribute "viewBox".
you're right, we should handle some exception to make it works well
@chris we can just write "stroke-width":2, tested it, works great. omit the replace before v[p] and use quotes in the attribute name if there is a dash in it. mixing unquoted simple attributes and quoted-dashed ones works too.
45

Add this to html:

<svg id="mySVG" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"/>

Try this function and adapt for you program:

var svgNS = "http://www.w3.org/2000/svg";  

function createCircle()
{
    var myCircle = document.createElementNS(svgNS,"circle"); //to create a circle. for rectangle use "rectangle"
    myCircle.setAttributeNS(null,"id","mycircle");
    myCircle.setAttributeNS(null,"cx",100);
    myCircle.setAttributeNS(null,"cy",100);
    myCircle.setAttributeNS(null,"r",50);
    myCircle.setAttributeNS(null,"fill","black");
    myCircle.setAttributeNS(null,"stroke","none");

    document.getElementById("mySVG").appendChild(myCircle);
}     

Comments

0

Elements can easily be added using the fragment.

Example

<input style="width:300px" type="text" placeholder="Input something to change the text." /><br>
<script>
const frag = document.createRange().createContextualFragment(`
<svg width="250" height="250">
  <rect x="0" y="0" width="250" height="250" fill="#95B3D7"></rect>
  <a href="https://www.google.com" style="cursor: pointer" target="_blank">
    <text x="10" y="130" style="
      font-size: 48px;
      fill:#faff00;">
      Hello world</text>
  </a>
</svg>
      `)
      const textElem = frag.querySelector("text")
      document.querySelector("input").onchange = (e) => {
        textElem.textContent = e.target.value
      }
      document.body.append(frag)
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.