Is it possible to append CSS keyframe animation with d3

In a HTML I can do this

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>


<body>
 <link rel="stylesheet" href="style.css"></link>
    
<svg xmlns="http://www.w3.org/2000/svg" >

   <style type="text/css">
  <![CDATA[
    .pulse {
  fill: blue;
  fill-opacity: 0;
  transform-origin: 50% 50%;
  animation-duration: 2s;
  animation-name: pulse;
  animation-iteration-count: infinite;
  animation-timing-function : cubic-bezier(.17,.67,.83,.67)
}

@keyframes pulse {
  from {
    stroke-width: 4px;
    stroke-opacity: 1;
    transform: scale(0.3);
  }
  to {
    stroke-width: 0;
    stroke-opacity: 0;
    transform: scale(2);
  }
}

  
  ]]>

</style>
            
          <circle class = "pulse" cx = "50%" cy = "50%" r = "5px" stroke= "black"></circle>
        </svg>
<script type="text/javascript">
	</script>

</body>

</html>

How can I utilize d3 to write this keyframe animation? this is what I tried which did not work. I asssigned the style attribute correctly buut I could not append the keyframe statement.

I donโ€™t want to achieve this with SMIL, although setting SMIL attribute for the circles would be pretty straightforward.

A notebook

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>


<body>
 <link rel="stylesheet" href="style.css"></link>
    
<svg xmlns="http://www.w3.org/2000/svg" >

           
          <circle class = "pulse" cx = "50%" cy = "50%" r = "5px" stroke= "black"></circle>
        </svg>
<script type="text/javascript">

	d3.select('.pulse')
		.style('fill','blue')
		.style('fill-opacity','0')
		.style('transform-origin','50% 50%')
		.style('animation-duration','pulse')
		.style('animation-name','pulse')
		.style('animation-iteration-count','infinite')
		.style('animation-timing-function','cubic-bezier(.17,.67,.83,.67)')
		
	</script>

</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>


<body>
    <!--<link rel="stylesheet" href="style.css"></link>-->

    <svg xmlns="http://www.w3.org/2000/svg">


		<circle class="pulse" cx="50%" cy="50%" r="5px" stroke="black"></circle>
	</svg>
    <script type="text/javascript">
        const style =
            d3.select('body')
            .append('style')
            .attr('type', 'text/css')

        //generate this bit dynamically
        const keyFrame = `
		.pulse {  
			fill-opacity: 0;
			transform-origin: center;
			animation-duration: 2s;
			animation-name: pulse;
			animation-iteration-count: infinite;
			animation-timing-function : cubic-bezier(.17,.67,.83,.67)
			}

			@keyframes pulse {
			from {
				stroke-width: 4px;
				stroke-opacity: 1;
				transform: scale(0.3);
			}
			to {
				stroke-width: 0;
				stroke-opacity: 0;
				transform: scale(2);
			}
		}
		`
        d3.select('.pulse').style("pointer-events", "all")
            .on('mouseenter', () => {
                style['_groups'][0][0].innerHTML = keyFrame
            })
            .on('mousemove', () => {
                style['_groups'][0][0].innerHTML = keyFrame
            })
            .on('mouseover', () => {
                style['_groups'][0][0].innerHTML = keyFrame
            })
            .on('mouseleave', () => {
                style['_groups'][0][0].innerHTML = null
            })
    </script>

</body>

</html>
1 Like