The getTotalLength() method in SVG may not provide an accurate size measurement when dealing with non-scaling-stroke. To obtain the correct scale of

In my current project, I am utilizing JavaScript to determine the length of a path and apply half of that length to the stroke-DashArray. However, I have encountered an issue as I am using

vector-effect="non-scaling-stroke"
in order to maintain a consistent stroke-width:2px; regardless of scale. This property affects all aspects of the stroke properties, including DashArray, so I need to calculate the scale of the SVG in order to scale path.getTotalLength();.

Is there a method in JavaScript to retrieve the computed scale of the SVG, which I can then use as a multiplier for the path length?

To illustrate this issue, I have created a demo on codepen.io. Feel free to resize the viewport to observe the changes in the stroke.

Answer №1

Let's highlight Sam's insightful comment/answer that really helped me!

To calculate the scale number, try using path.getBoundingClientRect().width/path.getBBox().width

To determine the length of the path, simply multiply the scale by path.getTotalLength() * scale;

Answer №2

If you're having trouble with scaling your svg, the solution mentioned above didn't work for me either. This is probably because my svg isn't proportionally sized (it's set to fill the browser window). However, I found a simple fix using boundingClientRect and the pythagorean theorem:

let boundingClient = el.getBoundingClientRect();
let pathLength = Math.sqrt(boundingClient.width ** 2 + boundingClient.height ** 2);

This method worked perfectly for me and just requires recalculating whenever the window size changes.

Answer №3

In my opinion, the best approach is to calculate the viewbox size by dividing it with the SVG width.

  <!doctype html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head> 
  <body>
    <button onclick="dashAni(myPath, 50, 3500)">start</button>
    <svg id="mySVG"  width="200" height="200" viewBox="0 0 500 500">
        <path 
        vector-effect="non-scaling-stroke"
        id="myPath" d="M 50,250 c 0 -100   150 -100   200 0 
                                      c 50 100   200 100   200 0
                                      c -0 -100   -150 -100   -200 0
                                      c -50 100   -200 100   -200 0
                                      z" 
        stroke="#eee"
        stroke-width="5" fill="none" />
    </svg>
    <script>
      var dashAni = function(path, length, duration){
        var dashPath = path.cloneNode(true);
        mySVG.appendChild(dashPath);
        var pathLen=path.getTotalLength()/2.5;  
        var aktPos=0
        var sumSteps = duration / (1000/60) // 60 pics per second
        var step=0;
        var pathAnim;
        dashPath.setAttribute('stroke-dasharray', length + ' ' + (pathLen - length));
        dashPath.setAttribute('stroke', "red");
        dashPath.setAttribute('stroke-dashoffset', aktPos);

        var anim=function(){
           aktPos = pathLen/sumSteps*step*-1;
            //aktLen = easeInOutQuad(step/sumSteps)*len;
           dashPath.setAttribute('stroke-dasharray', length + ' ' + pathLen);
           dashPath.setAttribute('stroke-dashoffset', aktPos);

           if (step <= (sumSteps)){
            step++;
            pathAnim = setTimeout(anim, 1000/60) //1000/60 pics/second
            } else {
              mySVG.removeChild(dashPath);
              clearTimeout(pathAnim);
            }
        }
       anim();
      }
    </script>
  </body>
  </html>
  

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering issues with implementing router.push in Reactjs

Currently, I am working on ReactJS and utilizing Next.js. My current task involves refreshing the page (using routes), but I encountered an error message stating: Error: No router instance found. You should only use "next/router" inside the client-side of ...

Utilize jQuery to extract the content, rearrange the content, and then encapsulate it within fresh

I attempted all day to rearrange this menu the way I want, but since I am new to jQuery, I'm facing some challenges. Here is what I am currently trying to achieve: Inside the last td.top of this menu, there are 3 ul.sub li items. I aim to extract ...

Tips for presenting JSON data retrieved using jQueryWould you like to know how

Is there a way to extract and display the user id from JSON values? I'm trying to access the user id value. $('User_id').observe('blur', function(e) { var txt = $('User_id').value; jQuery.ajax({ type: 'g ...

Assign specific CSS classes to elements based on the v-model value in Vue.js

Looking to create a dynamic table using Vue and trying to add a class to a row when a checkbox is checked. Each checkbox is associated with a specific value in an object of objects. View the code on Codepen. <tbody> <tr v-for="row in filter ...

Having trouble importing XML data from an external file with jQuery

Attempting to import external XML with the code below is proving unsuccessful $( document ).load( "data.xml", function( response, status, xhr ) { console.log( xhr.status + " " + xhr.statusText ); }); Both data.xml and js files are in the ...

Are there any options available for customizing the animation settings on the UI-bootstrap's carousel feature?

If you're interested in seeing an example of the standard configuration, check out this link. It's surprising how scarce the documentation is for many of the features that the UIB team has developed... I'm curious if anyone here has experie ...

JSON output for creating interactive charts using Highcharts

After much perseverance, I have successfully generated a chart. However, I am facing an issue where the data from JSON is not being displayed - resulting in a blank chart. The chart options currently look like this: series : [{ name: '2000' ...

Retrieve the value of an object from a string and make a comparison

var siteList = {}; var siteInfo = []; var part_str = '[{"part":"00000PD","partSupplier":"DELL"}]'; var part = part_str.substring(1,part_str.length-1); eval('var partobj='+part ); console.log(par ...

Issue with retrieving POST body from Ajax call in Play Framework

I am currently attempting to send a POST request to my backend using JSON data. The frontend call appears like this: function register() { var user = $("#form_reg_username").val(); var pass = $("#form_reg_password").val(); var referal = $("#form_reg ...

Dynamic web page updates from server using an Ajax request

I have a JavaScript client application and an Express.js server. I am looking to update a page on my server with information sent through an AJAX call from my client application. I need the page to be updated in real-time. Here is the code snippet in my ...

Load various types of classes and run functions with matching names

I have encountered a challenging issue that needs to be resolved. Imagine having multiple classes located in a directory named services. These classes all include a constructor() and send() method. Examples of such classes can be Discord, Slack, SMS, etc. ...

Load Vue 3 components dynamically using a string-based approach

Exploring ways to dynamically load components based on a string input. Here is an attempt at achieving this: <component v-for="component in components" :is="eval(component)" /> However, this approach does not yield the desired r ...

Ways to effectively test a custom hook event using Enzyme and Jest: A guide on testing the useKeyPress hook

Looking for guidance on testing a custom hook event called useKeyPress with Enzyme and Jest This is my current custom hook for capturing keyboard events and updating keyPress value: import React, { useEffect, useState } from 'react' const useKe ...

Is it a common occurrence for AJAX applications utilizing POST requests to encounter issues in Internet Explorer?

After some investigation, I have come across a bug in Internet Explorer that is causing intermittent failures for users running my application. This bug exists within the HTTP stack of IE and impacts all applications utilizing POST requests from this brows ...

Top method for detecting errors in Models? (Node.js + Sequelize)

Looking for a straightforward method to catch errors in an API using Node.js and Sequelize models? Take a look at this code snippet which utilizes async-await: const router = express.Router() const { Operations } = require('../models') router.po ...

Ways to determine the port being utilized in NodeJS

After executing the process with npm run start I want to keep track of the port being used. Is there a command available for this monitoring purpose? ...

Tips for sending context in the success callback function of a jQuery AJAX request

const Box = function(){ this.parameters = {name:"rajakvk", year:2010}; Box.prototype.callJsp = function() { $.ajax({ type: "post", url: "some url", success: this.executeSuccess.bind(this), err ...

Easy Steps to Align a Rotated Table Header

I am looking to rotate the header table using CSS while keeping all text together. Here is my CSS code: th.rotate { height: 100px; white-space: nowrap; } th.rotate>div { transform: rotate(-90deg); } Here is how I have applied this CSS: ...

Guide to excluding all subdependencies using webpack-node-externals

My current setup involves using webpack to bundle both server assets and client code by specifying the target property. While this configuration has been working well, I encountered an issue where webpack includes all modules from node_modules even for ser ...

The Datatable feature is malfunctioning, unable to function properly with Javascript and JQuery

As a novice in the world of jquery/javascript, I find myself struggling with what may seem like an obvious issue. Despite following tutorials closely (the code for the problematic section can be found at jsfiddle.net/wqbd6qeL), I am unable to get it to wor ...