38

i was using raphaeljs , and i want to show html(not only text) in svg,

so i use this code :

var r = Raphael("holder", 200, 300);
var t = r.text(10, 10, "ssdwqdwq");
t.node.innerHTML='dddd'

but i cant change the svg's content , so i console it in firebug ,

console.log(t.node)

it show this :

<text x="10" y="13.5" text-anchor="middle" style="font: 10px "Arial";" font="10px "Arial"" stroke="none" fill="#000000">

so how to change the text using javscript on svg

thanks

zjm1126
  • 34,604
  • 53
  • 121
  • 166

6 Answers6

86

SVG nodes don't have a innerHTML property (they're not HTML).

Use textContent instead: t.node.textContent='dddd'

Zecc
  • 4,220
  • 19
  • 17
14

I was able to accomplish this by setting the textContent property of the <text> element. Makes it a lot easier if you know the ID of the element.

document.getElementById("id-of-text-el").textContent = "My Value";
contactmatt
  • 18,116
  • 40
  • 128
  • 186
8

if the code for the svg text is like this:

<text id="id-of-the-text"> old value</text>

if you are using JQuery try this:

$("#id-of-the-text").text("new-value");
Emre Basala
  • 409
  • 4
  • 9
  • Or, without the burden of jQuery: `document.querySelector('text#id-of-the-text').textContent='new-value';`. This looks longer, but jQuery runs through about a hundred lines of code before doing the same thing. – Manngo Sep 21 '21 at 23:54
0

In addition to Zecc's answer - it IS possible to use innerHtml to get content of SVG elements, for example( that i'm sure of) - of text element and of a svg path

xlr8
  • 1
  • 1
  • 1
    This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33939643) – Zsolt Meszaros Mar 04 '23 at 15:21
0

Changing ìnnerHTML property for svg elements might have been a problem in 2010.

2023 it works flawlessly in all modern browsers:

// OP's example 
var r = Raphael("holder", 200, 300);
var t = r.text(50, 50, "ssdwqdwq").attr({
  'font-size': 20,
  'font-family': 'Arial',
  'font-weight': 'bold',
  fill: '#000',
  width: 400
});
t.node.innerHTML='dddd';

/**
* add foreignObject 
* to enable HTML elements
* make sure to apply the correct namespaces 
* for <foreignObject> and inner <div>
*/
let nsSvg = 'http://www.w3.org/2000/svg'
let nsHtml = 'http://www.w3.org/1999/xhtml'
let foreignObject = document.createElementNS(nsSvg, 'foreignObject');
foreignObject.setAttribute('x', 20)
foreignObject.setAttribute('y', 50)
foreignObject.setAttribute('width', '100%')
foreignObject.setAttribute('height', 150)

let foreignObjectDiv = document.createElementNS(nsHtml, 'div');
foreignObjectDiv.innerHTML = `Foreign <em style="color:red">object</em> <strong>text</strong>`;
foreignObject.appendChild(foreignObjectDiv)

//append foreign object
r.canvas.appendChild(foreignObject)
svg{
  border: 1px solid #ccc
}

text{
  font-size:20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.3.0/raphael.min.js"></script>
<div id="holder"></div>

Append HTML elements to SVG via <foreignObject>

It is crucial to use the correct namespaces when attaching the foreign object dynamically:

// foreignObject is a svg 
let foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
// HTML element within foreign object
let foreignObjectDiv = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');

Keep in mind, foreignObject will only work in applications with HTML rendering support.

A lot of graphic/desktop applications might omit its content.
You might also encounter issues trying to convert your svg to pdf in some libraries.

If you don't need complex multiline text layouts, you should better stick with SVG's native <text> and <tspan> elements.

herrstrietzel
  • 11,541
  • 2
  • 12
  • 34
0

My transpiler does not have the definition of textContent property and I found an another answer in this 2879473 question.

while (t.node.hasChild) {
    t.node.removeChild(t.firstChild);
}
var txt = document.createTextNode("ddd");
t.node.appendChild(txt);

you can get same results by innerHTML, but DOM API may be a bit faster than property. see Maxim answer

(Sorry, I did not test createTextNode and appendChild spped)

kuri65536
  • 166
  • 2
  • 8