Create animations for SVG paths and polygons that move along specified paths

I am trying to animate both a path and a polygon in an SVG arrow along the same path. Currently, I have successfully animated the path using CSS, but I am struggling to figure out how to move the polygon along the path at the same pace.

<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.66 397" width="242.66" height="397">
<style>.cls-1{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:bevel;stroke-width:4px;}</style>
  <path class="cls-1" d="M240.66,2C11.72,114.98-26.67,239.75,19.39,392.85"/>
  <polygon points="0 384.74 2.04 381.29 19 391.37 27.81 373.72 31.39 375.51 20.65 397 0 384.74"/>
</svg>

I have already applied animation to the path with successful results using the following CSS code:

path {
  stroke: #000000;
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash 4s linear forwards;
}

@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}

However, I have attempted to animate the polygon using the code below, but it is not working as expected:

polygon {
  offset-distance: 0%;
  offset-path: path('M240.66,2C11.72,114.98-26.67,239.75,19.39,392.85');
  animation: move 2.1s linear forwards infinite;
}

@keyframes move {
  100% {
    offset-distance: 100%;
  }
}

If anyone can provide insight on how to properly animate the polygon along the same path as the path element, it would be greatly appreciated!

Answer №1

The arrow's rotation and position are determined by the offset-path.

Whether using css offset-path or svg SMIL <mpath>, your animated element should point towards the x/y origin of your svg, as shown below:

https://i.sstatic.net/ZsK0C.png

Your arrow is already positioned on the path – the browser will add the current x/y values to the coordinates along your motion path.
In this scenario: your arrow disappears due to large offsets. (see left example.)

.wrp {
  padding: 1em;
  //border: 1px solid #ccc;
  display: inline-block;
}

svg {
  display: inline-block;
  width: 10em;
  overflow: visible;
  border: 1px solid #ccc;
}

.motionPath {
  stroke: #000;
  stroke-dasharray: 0 100;
  animation: dash 2s linear forwards infinite;
}

.arrow {
  offset-distance: 0%;
  offset-path: path('M240.66,2C11.72,114.98-26.67,239.75,19.39,392.85');
  animation: move 2s linear forwards infinite;
}

polygon {
  offset-distance: 0%;
  offset-path: path('M240.66,2C11.72,114.98-26.67,239.75,19.39,392.85');
  animation: move 2s linear forwards infinite;
}

@keyframes dash {
  to {
    stroke-dasharray: 100 100;
  }
}

@keyframes move {
  100% {
    offset-distance: 100%;
  }
}
<div class="wrp">
  <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.66 397">
  <style>
    .cls-1 {
      fill: none;
      stroke: #000;
      stroke-linecap: round;
      stroke-linejoin: bevel;
      stroke-width: 4px;
    }
  </style>
  <path class="cls-1 motionPath" d="M240.66,2C11.72,114.98-26.67,239.75,19.39,392.85" pathLength="100" />
  <path class="arrow" stroke="red" fill="none" stroke-width="4" d="M-12.5 -12.5 l 12.5 12.5 l-12.5 12.5"></path>
</svg>

</div>


<div class="wrp">
  <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 242.66 397">
<style>.cls-1{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:bevel;stroke-width:4px;}</style>
  <path class="cls-1 motionPath" d="M240.66,2C11.72,114.98-26.67,239.75,19.39,392.85" pathLength="100"/>
  <polygon fill="red" style="transform:translate(-25px, -300px)" points="0 384.74 2.04 381.29 19 391.37 27.81 373.72 31.39 375.51 20.65 397 0 384.74"/>
</svg>
</div>

I have substituted your arrow with another <path> element, but you can adjust the original arrow polygon in an editor like Inkscape to get the correct coordinates and rotation.

You must also specify a pathLength or calculate the exact pathLength using JS like path.getTotalLength()

Otherwise, you won't be able to synchronize your stroke animation with the arrow's movement.

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

Customizing Material-UI elements in React using CSS styling

My goal is to style all the <Chip> elements within a <Grid> that has the class .table-header, but they are not changing their style (I have a <p> that should be colored in red and it works). Why does the styling work for the <p> ele ...

The child element is bigger than its parent due to the maximum height set. There is no visible overflow

My goal is to create a parent element with a maximum height, and have a child element fill this parent. If the content in the child exceeds the parent's dimensions, a scrollbar should appear. I attempted to achieve this by: div.parent { max-hei ...

Tips for creating PrimeNG tables with columns that automatically adjust in size

Is there a way to automatically adjust and resize the columns in my PrimeNG table? I'm looking for a method to make this happen. Can you help me achieve this? ...

Leveraging the Scroll feature in Bootstrap for smooth scrolling

Seeking assistance with implementing scroll in Bootstrap 5 on my child component (ProductList.vue). Can anyone guide me on how to integrate the code? I have been searching for a solution without success. Below is the Bootstrap 5 code on the child component ...

The utilization of CSS variables within intricate properties

Imagine having a CSS property called box-shadow: box-shadow: 5px 5px 0 #ccc; What if there is a need to create a variable from the color #ccc? While in SCSS, you could accomplish this with code like: $grey: #ccc; .element { box-shadow: 5px 5px 0 $gre ...

Having issues with implementing the Bootstrap form-check-inline feature

I have been attempting to utilize the form-check-inline feature from Bootstrap Forms without success, as it seems to be stacking checkboxes vertically instead of inline: https://i.sstatic.net/paLTC.png This is the code snippet I am working with: <h1& ...

What steps can I take to direct mobile visitors to the mobile-friendly version of my website?

Looking for a way to automatically redirect users on mobile devices from www.domain.com to the new mobile version at m.domain.com? ...

What is the process of uploading a video and showcasing it on an HTML page?

I have successfully uploaded images and displayed them on an HTML page. Now, I am looking to do the same for videos. Here is my current code: $('#addPhotosBtn').click(function() { $(this).parents().find('#addPhotosInput').click(); }) ...

Display fewer search results initially and have the option to view more when hovering

I am working with a PHP function that generates a ul element. <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> <li>Item 5</li> I am looking to display the list in a li ...

CSS - my expectations of reduced content were not met

I'm attempting to create a responsive content box that shrinks properly when the browser size is reduced. https://i.sstatic.net/wQD8j.png However, I am facing an issue where the content (yellow) does not shrink and instead overflows horizontally whe ...

Using jQuery to toggle the image of a button based on its id

I have a jQuery function that opens another section when clicking on a div with the class 'open', and changes the image of a button by switching its id for CSS. However, I now need to change the button's image back when it is clicked again. ...

Trouble organizing a collection of destinations based on their geolocation and proximity

To address this issue, my approach has been to feed variables into the value attributes of an option list and then sort it based on these values. When manually assigning values, everything works smoothly, for example: <option id="link1" value="1">A& ...

Transform the functionality of DIV and UL to mimic that of a SELECT element

I am attempting to update the text of the <span class="hideSelect"> element to match the text of the selected <li>, so that it functions like a <select> element. CSS: .myDrop { border: 1px solid #ddd; border-radius: 3px; padding: ...

Steps for choosing an image and embedding it within a div element

Upon loading the site, an image is displayed with the following code: <img id="some_Image" src="some_source"> However, I am looking to avoid requesting this image again from "some_source". This is because calculating the image can be resource-inten ...

Banner advertisement on a webpage

Currently, I am working on a website project for clients who are interested in having background ads displayed throughout the entire site. In terms of coding this feature with CSS, it is relatively straightforward: body { background-image: url('a ...

Using a background image in the navigation menu with CSS

Looking to create a horizontal menu with a responsive background image. Struggling with the issue of the 'ul' menu being misaligned with the background image when in full-screen mode. Attempted to use separate 'div' containers for the ...

Adjust the height of the HTML overlay to span the entire visible page

I have a website that utilizes AJAX to load content dynamically. To enhance user experience, I implemented an overlay with a loading indicator during the loading process using jQuery and the jQuery BlockUI plugin. When invoking $(element).block(), everyth ...

The function view() is not displaying the CSS and JS files properly

Having trouble with loading the css and js on my view: This is how I set up the controller: return view('home.news') ->with("news", $news); And here's how the route is defined: Route::get('/news/{id}&apos ...

Minimize the width to display a scrollbar

Check out this page: where you'll find the same code snippet displayed twice - once through GitHub Gist embedding and the second using Jekyll's internal syntax highlighter Rouge. I'm currently working on styling the second code snippet to m ...

CSS to Reverse Align Navigation Bar Text

I'm currently working on my first website and I've encountered a problem with the Navigation Bar. Using CSS rules to align the bar, I noticed that when I apply float:right;, the text floats to the right but ends up aligning backwards on the bar. ...