Home > Net >  Re-Center text position as str length changes
Re-Center text position as str length changes

Time:06-03

I am new to javascript and am having an issue repositioning animated text as the string length varies. I have an SVG element and a string within it, where that string needs to be centered within that SVG. Using ' | ' as a center reference, the centering would look like:

   |      |      |
 g g g   g g     g

If I start the animation with a str of len 3, it will be centered properly for Len 3 strs, but then other lens would be equivalent to:


  |     |
g g   g 

Example code:

function animateValue(obj, start, end, duration) {
  let startTimestamp = null;
  const step = (timestamp) => {
    if (!startTimestamp) startTimestamp = timestamp;
    const progress = Math.min((timestamp - startTimestamp) / duration, 1);
    const str = obj.innerHTML;
   // console.log(`${str.length}` );
    if (`${str.length}`==="1"){
      obj.style.x =  '200px';
    }
    obj.innerHTML = Math.floor(progress * (end - start)   start);
    if (progress < 1) {
      window.requestAnimationFrame(step);
    }
  };
  window.requestAnimationFrame(step);
}
const obj = document.getElementById("heading");
animateValue(obj, 100, 0, 5000);
svg { 
    position: absolute ;
    width: 40%;
    border: 1px solid rgba(255,255,255,0.3);
    margin-left: 30%;
    border-radius: 50%;
  }
#roseline, #majline {
  stroke: #eee;
  stroke-width: .5;
}
text {
    font-family: Montserrat, sans-serif;
    font-size: 10;
    fill: #eee;
}


text.heading1{
  font-size:4.5em;
  fill: #0ee;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" id="compassrose">

<defs>
  <symbol>
    <line x1="40" y1="250" x2="50" y2="250" id="roseline" />
    <line x1="40" y1="250" x2="60" y2="250" id="majline" />
    <path d="M10,250a240,240 0 1,0 480,0a240,240 0 1,0 -480,0" id="rosecircle"  transform='rotate(90 250 250)' />  

  </symbol>
  </defs>


 <div >
                <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" id="compassrose">
                      <polygon points="250,40 280,0 220,000"  />

            </svg>
            <svg xmlns="http://www.w3.org/2000/svg"       xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" >
                <polygon points="0,260 0,220 40,240" />

              </svg>
             <svg xmlns="http://www.w3.org/2000/svg"       xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" >
               <polygon points="500,260 500,220 460,240" />
               

   <text  id="heading"  x='190px' y='250px'
      fontSize="36">100 </text>

              </svg>


    </div>

</svg>

I have tried re-arranging the divs to allow for the absolute and relative positioning, however that was not properly maintaining size relationships as needed.

CodePudding user response:

If you use dominant-baseline="middle" text-anchor="middle" on the text element and position it in the middle of the SVG (250,250) it should work.

function animateValue(obj, start, end, duration) {
  let startTimestamp = null;
  const step = (timestamp) => {
    if (!startTimestamp) startTimestamp = timestamp;
    const progress = Math.min((timestamp - startTimestamp) / duration, 1);
    obj.innerHTML = Math.floor(progress * (end - start)   start);
    if (progress < 1) {
      window.requestAnimationFrame(step);
    }
  };
  window.requestAnimationFrame(step);
}
const obj = document.getElementById("heading");
animateValue(obj, 200, 0, 5000);
svg {
  display: block;
  position: absolute;
  width: 40%;
  border: 1px solid rgba(255, 255, 255, .3);
  margin-left: 30%;
  border-radius: 50%;
}

#roseline,
#majline {
  stroke: #eee;
  stroke-width: .5;
}

text {
  font-family: Montserrat, sans-serif;
  font-size: 10;
  fill: #eee;
}

text.heading1 {
  fill: #0ee;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" id="compassrose">
  <defs>
    <symbol>
      <line x1="40" y1="250" x2="50" y2="250" id="roseline" />
      <line x1="40" y1="250" x2="60" y2="250" id="majline" />
      <path d="M10,250a240,240 0 1,0 480,0a240,240 0 1,0 -480,0"
        id="rosecircle"  transform='rotate(90 250 250)' />  
    </symbol>
  </defs>
  <polygon points="250,40 280,0 220,000"  />
  <polygon points="0,260 0,220 40,240" />
  <polygon points="500,260 500,220 460,240" />
  <text  id="heading"  x="250" y="250" font-size="60"
    dominant-baseline="middle" text-anchor="middle">100</text>
</svg>

  • Related