How to get the SVG document content inside an object tag in JavaScript All In One

xgqfrms / 2023-08-31 / 原文

How to get the SVG document content inside an object tag in JavaScript All In One

object tag & SVG document

solution 1

Outside the SVG create an absolute position div as a tooltip container, and add the mouse event listener on SVG texts dynamic set its content to the tooltip.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <text x="0" y="15" fill="red" id="red1">I love SVG</text>
  <text x="10" y="25" fill="green" id="green2">I love SVG 2</text>
</svg>

PS: The ./texts.svg file must be run on a server without CORS issues.

<!DOCTYPE html>
<html lang="zh-Hans">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="author" content="xgqfrms">
    <meta name="generator" content="VS code">
    <script src="https://unpkg.com/@popperjs/core@2"></script>
    <script src="https://unpkg.com/tippy.js@6"></script>
    <style lang="css">
      #tip {
        position: absolute;
        top: 0;
        left: 0;
        background: #000;
        color: #0f0;
      }
      #svgObject {
        margin-top: 100px;
        margin-left: 100px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div id="tip">
        <span id="hack"></span>
      </div>
      <object id="svgObject" class="atac-svg-tranlator" data="./texts.svg" type="image/svg+xml" width="400" height="300"></object>
    </div>
    <footer>
      <p>copyright&copy; xgqfrms 2023</p>
    </footer>
    <script>
      window.addEventListener("load", (event) => {
        const body = document.body;
        const tip = document.getElementById('tip');
        const svgObject = document.getElementById('svgObject');
        const svgDoc = svgObject.contentDocument.querySelector("svg")
        if (svgDoc) {
          const textElements = svgDoc.querySelectorAll('text');
          textElements.forEach(function(textElement) {
            const text = textElement.textContent
            textElement.addEventListener('mouseleave', (event) => {
              tip.innerHTML = `<span id="hack"></span>`
              tip.setAttribute(`style`, `top: 0px; left: 0px;`)
            })
            textElement.addEventListener('mouseenter', (event) => {
              const y = event.screenY - event.clientY - 80
              const x = event.screenX - event.clientX + 18
              tip.innerHTML = `<span id="hack">${text}</span>`
              tip.setAttribute(`style`, `top: ${y}px; left: ${x}px;`)
              // title property not work ❌
              textElement.setAttribute('title', text);
              textElement.setAttribute('style', `cursor: pointer;`);
            })
            textElement.addEventListener('click', (event) => {
              console.log(`click`, event)
            })
            // tippy(textElement, {
            //   content: text,
            //   placement: 'top',
            // });
            // Bug reproduction steps, the mouse hovers over the svg text
            // ❌ core@2:5 Uncaught TypeError: Cannot read properties of null (reading 'body')
            // https://atomiks.github.io/tippyjs/
            // https://github.com/atomiks/tippyjs/issues/1137
          });
        } else {
          console.log('SVG document not loaded');
        }
      });
    </script>
  </body>
</html>

image

solution 2

Add the mouse event listener on SVG texts, then dynamic create an SVG <Title> tag, and insert it into SVG with text content.

// todo

demos

image

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <!-- <script src="https://d3js.org/d3.v4.js"></script> -->
    <!-- <link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css"/> -->
    <script src="https://unpkg.com/@popperjs/core@2"></script>
    <script src="https://unpkg.com/tippy.js@6"></script>
    <style lang="css">
      #tip {
        /* position: fixed; */
        position: absolute;
        top: 0;
        left: 0;
        background: #000;
        color: #0f0;
      }
    </style>

  </head>
  <body>
    <div class="container">
      <section>
        <button id="myButton">My button</button><br>
        <a href="" title="link 😂" alt="link">link</a> <br>
        <span title="span 😂" alt="span" id="span">span</span><br>
        <input title="button 😂" type="button" value="btn" />
        <div title="😂 div">div</div>
      </section>
      <div id="tip">
        <span id="hack"></span>
      </div>
      <section>
        <svg xmlns="http://www.w3.org/2000/svg" version="1.1" title="svg 😂">
          <text x="0" y="15" fill="pink" id="pink" title="text 😂">I love SVG<title>Tooltip 2</title></text>
        </svg>
      </section>
     <object id="svgObject" class="atac-svg-tranlator" data="./shit.svg" type="image/svg+xml" width="400" height="300"></object>
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="./texts.svg" type="image/svg+xml" width="400" height="300"></object> -->
     <object id="svgObject" class="atac-svg-tranlator" data="https://cdn.xgqfrms.xyz/svg/texts.svg" type="image/svg+xml" width="400" height="300"></object>
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="https://cdn.xgqfrms.xyz/svg/seat.svg" type="image/svg+xml" width="400" height="300"></object> -->
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="./text3.svg" type="image/svg+xml" width="400" height="300"></object> -->
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="https://www.runoob.com/try/demo_source/text3.svg" type="image/svg+xml" width="400" height="300"></object> -->
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="https://cdn.xgqfrms.xyz/icons/html5.svg" type="image/svg+xml" width="400" height="300"></object> -->
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="https://cdn.xgqfrms.xyz/icons/vscode-dev.svg" type="image/svg+xml" width="400" height="300"></object> -->
     <!-- <object id="svgObject" class="atac-svg-tranlator" data="./src/assets/images/test.svg" type="image/svg+xml" width="400" height="300"></object> -->
    </div>
        <!-- <script id="" src="dist/app.js"></script> -->
        <!-- <script>

const svgObject = document.getElementById('svgObject');

svgObject.addEventListener('load', function() {
  const svgDoc = svgObject.contentDocument;
  window.svgDoc = svgDoc
  console.log(`svgObject.contentDocument`, svgObject.contentDocument)
  console.log(`svgObject.innerHTML`, svgObject.innerHTML)
  if (svgDoc) {
    const textElements = svgDoc.querySelectorAll('text');
    console.log(`textElements`, textElements)
    // textElements.forEach(function(textElement) {
    //   // Create Tippy tooltip for each text element
    //   tippy(textElement, {
    //     content: textElement.textContent,
    //     appendTo: svgDoc.documentElement,
    //     placement: 'top',
    //   });
    // });
  } else {
    console.log('SVG document not loaded');
  }
});
        </script> -->

        <script>


          // window.addEventListener ✅
          window.addEventListener("load", (event) => {
          // document.addEventListener('DOMContentLoaded', function() {
            tippy('#myButton', {
              content: 'My tooltip!',
            });
            /* tippy('#span', {
              content: 'span tooltip!',
            });
            console.log("page is fully loaded");
            const body = document.body;
            const tip = document.getElementById('tip'); */
            // window.obj = {
            //   text: '❌'
            // }
            // tippy('#tip', {
            //   content: window.obj.text,
            //   // appendTo: tip,
            // });
   /*          const svgObject = document.getElementById('svgObject');
            console.log('✅ onload')

            console.log(`svgObject.contentDocument`, svgObject.contentDocument)
            console.log(`svgObject.innerHTML`, svgObject.innerHTML)
            console.log(`children`, svgObject.contentDocument.children)
            console.log(`body`, svgObject.contentDocument.body)
            console.log(`svg`, svgObject.contentDocument.querySelector("svg"))
            const svgDoc = svgObject.contentDocument.querySelector("svg") */
            const svgObject = document.getElementById('svgObject');
            console.log(`svgObject.innerHTML`, svgObject.innerHTML)
            console.log(`children`, svgObject.contentDocument.children)
            console.log(`body`, svgObject.contentDocument.body)
            console.log(`svg`, svgObject.contentDocument.querySelector("svg"))
            const svgDoc = svgObject.contentDocument.querySelector("svg")

            svgObject.addEventListener('load', function() {
              const svgDoc = svgObject.contentDocument; // Get the SVG document from the object element
              console.log(`❌ svgDoc`, svgDoc)
              if (svgDoc) {
                // Find and initialize tooltips for text elements within the SVG
                const textElements = svgDoc.querySelectorAll('text');
                textElements.forEach(function(textElement) {
                  // Create Tippy tooltip for each text element
                  tippy(textElement, {
                    content: textElement.textContent,
                    appendTo: svgDoc.documentElement,
                    placement: 'top',

                  });
                });
              } else {
                console.log('SVG document not loaded');
              }
            });
/*             window.svgDoc = svgDoc
            if (svgDoc) {
              const textElements = svgDoc.querySelectorAll('text');
              console.log(`textElements`, textElements)
              textElements.forEach(function(textElement) {
                // Create Tippy tooltip for each text element
                const text = textElement.textContent
                console.log(`textElement.textContent`, text);
                console.log(`textElement.innerHTML`, textElement.innerHTML);
                // textElement.addEventListener('mouseover', () => {
                //   console.log(`hover ✅`, textElement.id)
                // })
                textElement.addEventListener('mouseleave', (event) => {
                  console.log(`mouseleave 👻`)
                  // clear
                  // tip.innerHTML = `<mark>👻</mark>`
                  tip.innerHTML = `<span id="hack"></span>`
                  tip.setAttribute(`style`, `top: 0px; left: 0px;`)
                  // tippy('#hack', {
                  //   content: '',
                  // });
                })
                textElement.addEventListener('mouseenter', (event) => {
                  // console.log(`event =`, event)
                  const y = event.screenY - event.clientY - 80
                  const x = event.screenX - event.clientX + 18
                  console.log(`x, y, event =`, x, y, `\n`, event)
                  // screenX: 58, screenY: 368, clientX: 50, clientY: 0
                  // offsetX:51 offsetY: 1 pageX:50 pageY:0
                  console.log(`mouseenter ✅`, textElement.id)
                  // textElement.title = text;
                  textElement.setAttribute('title', text);
                  // tip.innerHTML = `<mark>${text}</mark>`
                  tip.innerHTML = `<span id="hack">${text}</span>`
                  tip.setAttribute(`style`, `top: ${y}px; left: ${x}px;`)
                  // window.obj.text = text;
                  // tippy('#tip', {
                  //   content: text,
                  //   // appendTo: tip,
                  // });
                  // tip.setAttribute(`left`, event.pageX)
                  // tip.setAttribute(`top`, event.pageY)
                  // textElement.innerHTML = "✅";
                  // tippy(textElement, {
                  // // tippy(`#${textElement.id}`, {
                  //   content: text,
                  //   // appendTo: svgDoc.documentElement,
                  //   appendTo: svgDoc,
                  //   // appendTo: svgObject,
                  //   // appendTo: textElement,
                  //   // appendT: textElements,
                  //   placement: 'top',
                  //   // arrow: true,
                  //   // animation: 'fade',
                  // });
                })
                textElement.addEventListener('focus', () => {
                  console.log(`focus ✅`, textElement.id)
                })
                // ❓ tooltips, https://atomiks.github.io/tippyjs/
                //
                // tippy(textElement, {
                // // tippy(`#${textElement.id}`, {
                //   content: text,
                //   // appendTo: svgDoc.documentElement,
                //   // appendTo: svgDoc,
                //   // appendTo: svgObject,
                //   // appendTo: textElement,
                //   placement: 'top',
                //   // arrow: true,
                //   // animation: 'fade',
                // });
                // bug 复现步骤,鼠标悬停在 svg 文字上方
                // ❌ core@2:5 Uncaught TypeError: Cannot read properties of null (reading 'body')
              });
            } else {
              console.log('SVG document not loaded');
            }
 */
            // svgObject.addEventListener('onload', function() {
            // svgObject.addEventListener('load', function() {
            //   console.log('\n❌')
            //   const svgDoc = svgObject.contentDocument;
            //   window.svgDoc = svgDoc
            //   console.log(`svgObject.contentDocument`, svgObject.contentDocument)
            //   console.log(`svgObject.innerHTML`, svgObject.innerHTML)
            //   console.log(`svg`, svgObject.contentDocument.children)
            //   console.log(`svg`, svgObject.contentDocument.body)
            //   console.log(`svg`, svgObject.contentDocument.querySelector("svg"))
            //   if (svgDoc) {
            //     const textElements = svgDoc.querySelectorAll('text');
            //     console.log(`textElements`, textElements)
            //     // textElements.forEach(function(textElement) {
            //     //   // Create Tippy tooltip for each text element
            //     //   tippy(textElement, {
            //     //     content: textElement.textContent,
            //     //     appendTo: svgDoc.documentElement,
            //     //     placement: 'top',
            //     //   });
            //     // });
            //   } else {
            //     console.log('SVG document not loaded');
            //   }
            // });
          });
                </script>
  </body>
</html>

refs

https://stackoverflow.com/questions/77005977/tippy-js-when-svg-is-embedded-in-an-html-object#77005977

https://stackoverflow.com/questions/8798745/how-to-get-html-elements-from-an-object-tag



©xgqfrms 2012-2021

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!