Search code examples
javascripthtmlanimationhyperlinkticker

Animated ticker in javascript with clickable objects - direction issues with the svg objects


UPDATED 11/04-2023

So I am trying to create an animated ticker using javascript and svg text elements however I have got something wrong with my animation direction not being straight across the screen horizontally and instead it goes leftward and downward, and it only does it up in the left corner of the screen this is driving me nuts!

To those suggesting I use some framework other than javascript, even libraries don't! as I am trying switch back to a "no frameworks" solution for my site as it seems no matter what you choose, all these frameworks and libraries that make your site looking all nice and lovey dovey get hacked and then you site is in the proverbial gutter and you need to rebuild. So this time I am KISS'ing it - This is the code I have so far, it is almost there it just stops before exiting fully now.

Updated code

    '''


    <!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>SVG Ani w/Clickable</title>
  <style>
    body, html {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
    }
    #svg-container {
      position: relative;
      overflow: hidden;
      height: 100%;
      width: 100%;
      white-space: nowrap;
    }
    .svg-container {
      position: absolute;
      width: auto;
      height: 30px;
    }
    .svg {
      display: inline-block;
      cursor: pointer;
    }
    .svg text {
      fill: #333;
      font-size: 14px;
      font-family: Arial, Helvetica, sans-serif;
    }
  </style>
</head>
<body>
  <div id="svg-container"></div>

  <script>
    const links = [
      { text: 'Welcome to a soon fully revamped site - using AI to construct it - click to learn more.', href: './aiwork.html' },
    ];

    const duration = 9000;
    const spacing = 20;

    function createSVGObject(link) {
      const div = document.createElement('div');
      div.classList.add('svg-container');

      const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
      const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
      const a = document.createElement('a');

      text.setAttribute('y', '20');
      text.setAttribute('font-family', 'Arial, Helvetica, sans-serif');
      text.textContent = link.text;
      
      svg.appendChild(text);
      a.appendChild(svg);
      div.appendChild(a);
      
      a.setAttribute('href', link.href);
      a.setAttribute('class', 'svg');
      
      const computedWidth = text.getComputedTextLength();
      div.style.width = (computedWidth + 10) + 'px';
      svg.setAttribute('width', (computedWidth + 10) + 'px');
      svg.setAttribute('height', '30');
      svg.setAttribute('viewBox', `0 0 ${computedWidth + 10} 30`);
      svg.style.overflow = 'visible';

      return div;
    }

    function animateSVGObject(object) {
      object.style.top = '0';
      object.style.left = window.innerWidth + 'px';

      const startTime = performance.now();
      requestAnimationFrame(function animate(time) {
        const progress = (time - startTime) / duration;
        const distance = (window.innerWidth + object.getBoundingClientRect().width + spacing) * progress;
        const currentPosition = window.innerWidth - distance;
        object.style.left = currentPosition + 'px';

        if (currentPosition + object.getBoundingClientRect().width > -object.getBoundingClientRect().width) {
          requestAnimationFrame(animate);
        } else {
          setTimeout(() => {
            object.style.left = window.innerWidth + 'px';
            animateSVGObject(object);
          }, duration * links.length);
        }
      });
    }

    links.forEach((link, index) => {
      const svgObject = createSVGObject(link);
      document.getElementById('svg-container').appendChild(svgObject);
      setTimeout(() => animateSVGObject(svgObject), duration * index);
    });

  </script>

  <p>SVG</p>

</body>
</html>
    '''

Any takes on what I am doing wrong with the directionand why the svg does not animate all the way across my screen horizontally ?


Solution

  • This was what I ended up with for now

       <!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>SVG Aninimated Ticker With Clickable Hyperlinks </title>
          
          <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Einar Petersen - Science Fiction Writer and Technology Enthusiast</title>
            <link rel="stylesheet" type="text/css" href="ticker.css">
            <link rel="stylesheet" type="text/css" href="banner.css">
            <link rel="stylesheet" href="indexthumbnails.css">
            <link rel="stylesheet" type="text/css" href="navigation.css">
            <script src="scripts.js" defer></script>
            
        <meta name="description" content="... - This page in particular contains a SVG Aninimated Ticker With Clickable Hyperlinks">
        
          <style>
            body, html {
              margin: 0;
              padding: 0;
              height: 100%;
              width: 100%;
            }
            #svg-container {
              position: relative;
              overflow: hidden;
              height: 100%;
              width: 100%;
              white-space: nowrap;
            }
            .svg-container {
              position: absolute;
              width: auto;
              height: 30px;
            }
            .svg {
              display: inline-block;
              cursor: pointer;
            }
            .svg text {
              fill: #333;
              font-size: 14px;
              font-family: Arial, Helvetica, sans-serif;
            }
          </style>
        </head>
        
        
         
        
        
        <body>
          <div id="svg-container"></div>
        
          <script>
            const links = [
              { text: 'Welcome to a soon fully revamped site - using AI to construct it - click to learn more.', href: './aiwork.html' },
            ];
        
            const duration = 9000;
            const spacing = 20;
        
            function createSVGObject(link) {
              const div = document.createElement('div');
              div.classList.add('svg-container');
        
              const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
              const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
              const a = document.createElement('a');
        
              text.setAttribute('y', '20');
              text.setAttribute('font-family', 'Arial, Helvetica, sans-serif');
              text.textContent = link.text;
              
              svg.appendChild(text);
              a.appendChild(svg);
              div.appendChild(a);
              
              a.setAttribute('href', link.href);
              a.setAttribute('class', 'svg');
              
              const computedWidth = text.getComputedTextLength();
              div.style.width = (computedWidth + 10) + 'px';
              svg.setAttribute('width', (computedWidth + 10) + 'px');
              svg.setAttribute('height', '30');
              svg.setAttribute('viewBox', `0 0 ${computedWidth + 10} 30`);
              svg.style.overflow = 'visible';
        
              return div;
            }
        
            
        function animateSVGObject(object) {
          object.style.top = '0';
          object.style.transform = `translateX(${window.innerWidth}px)`;
        
          const startTime = performance.now();
          requestAnimationFrame(function animate(time) {
            const progress = (time - startTime) / duration;
            const distance = (window.innerWidth + object.getBoundingClientRect().width + spacing) * progress;
            const currentPosition = window.innerWidth - distance;
            object.style.transform = `translateX(${currentPosition}px)`;
        
            if (currentPosition + object.getBoundingClientRect().width > -spacing * 27) {
              requestAnimationFrame(animate);
            } else {
              setTimeout(() => {
                object.style.transform = `translateX(${window.innerWidth}px)`;
                animateSVGObject(object);
              }, duration * links.length);
            }
          });
        }
        
        
        
        
            links.forEach((link, index) => {
              const svgObject = createSVGObject(link);
              document.getElementById('svg-container').appendChild(svgObject);
              setTimeout(() => animateSVGObject(svgObject), duration * index);
            });
        
          </script>
        
          <p>SVG</p>
        
           
            <footer>
        <p>© 2023 .... All rights reserved.</p>
        <p>Some material on this website may be subject to different licenses, which will be clearly indicated where applicable.</p>
        <ul>
        <li><a href="...">... on Facebook</a></li>
        <li><a href="...">Follow ... @ Twitter</a></li>
        <li><a href="#">Instagram</a></li>
        <li><a href="...">Become a patron</a></li>
        
        </ul>
        </footer>
        </body>
        </html>