Highlight <tspan> inside <text> of svg

286 views Asked by At

I want to highlight only the inside not all the but the follow code not working. The filter background color has fill all the node

<!DOCTYPE html>
<html>
<body>

<svg height="30" width="200">
<defs> 
<filter id="solid">
  <feFlood flood-color="rgb(153, 255, 255)" result="bg"></feFlood>
  <feMerge>
    <feMergeNode in="bg"></feMergeNode>
    <feMergeNode in="SourceGraphic"></feMergeNode>
  </feMerge>
</filter>
</defs>
  <text x="0" y="15" fill="red">I love
  <tspan filter="url(#solid)">SVG!</tspan></text>
  Sorry, your browser does not support inline SVG.
</svg>
 
</body>
</html>

I want to set filter background width and position that only fill the text

1

There are 1 answers

0
herrstrietzel On

You can get the <tspan> bounding box via getBBox() and prepend or append a <rect> element with these coordinates:

hightlightSVGText()

function hightlightSVGText() {
  let highlighted = document.querySelectorAll("svg .highlight");
  highlighted.forEach((highlight) => {
    let svg = highlight.closest("svg");
    let textParent = highlight.closest("text");
    let bb = highlight.getBBox();
    let [x, y, width, height] = [bb.x, bb.y, bb.width, bb.height];

    let highlightRect = document.createElementNS(
      "http://www.w3.org/2000/svg",
      "rect"
    );
    highlightRect.setAttribute("x", x);
    highlightRect.setAttribute("y", y);
    highlightRect.setAttribute("width", width);
    highlightRect.setAttribute("height", height);
    highlightRect.classList.add("highlightRect");
    if (highlight.classList.contains('highlight-bg')) {
      highlightRect.classList.add("highlightRect-bg");
      svg.insertBefore(highlightRect, textParent);
    } else {
      highlightRect.classList.add("highlightRect-top");
      svg.insertBefore(highlightRect, textParent.nextElementSibling);
    }
  });
}
svg {
  width: 25%;
  border: 1px solid #ccc;
}

text {
  font-size: 10px;
}

.highlightRect {
  fill: cyan;
}

.highlightRect-top {
  mix-blend-mode: screen;
}
<svg viewBox="0 0 75 50">
  <text x="0" y="15" fill="red">I love
  <tspan class="highlight">SVG!</tspan></text>
  
  <text x="0" y="30" fill="red">I love
  <tspan x="0" dy="10" class="highlight highlight-bg">SVG!</tspan></text>
</svg>