SVG Morph

Morphing SVG shape using SMIL. Multiple keyframes.

by the_voder

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!--
REFERENCES:

(Very) comprehensive guide to SVG animation
https://css-tricks.com/guide-svg-animations-smil/
-->

<!-- Button container element (link for accessibility) -->
<a id="moonBTN" href="https://www.google.co.uk/">
	<!-- SVG element definition -->	
	<svg id="moon" viewbox="0 0 1000 1000">
		<!-- SVG internal stylesheet. Works like ordinary CSS styles, but some properties are unique to SVG (ie "fill") -->
		<style type="text/css">
			.svgMoon { fill: #fff; }
			.svgMoonBG { fill: #222; }
		</style>
		<!-- Moon background (delete this and associated CSS anove if not needed) -->
		<path class="svgMoonBG" d="M 1000,500c0,276.14-224.55,500-501.54,500C219.68,1000,0,776.14,0,500S226.86,0,498.46,0 C775.45,0,1000,223.86,1000,500 Z" />
		<!-- Moon path (begins with points for full moon) -->
		<path class="svgMoon" d="M 1000,500c0,276.14-224.55,500-501.54,500C219.68,1000,0,776.14,0,500S226.86,0,498.46,0 C775.45,0,1000,223.86,1000,500 Z">
			<!-- Define SVG animation. "Values" is list of points for 3 animation keyframes-->
			<animate
				id="moonAnim"
				attributeName="d"
				dur="500ms"
				repeatCount="0"
				begin="indefinite"
				fill="freeze"
				calcMode="linear"
				keyTimes="0; 0.7; 1"
				values="M 1000,500c0,276.14-224.55,500-501.54,500C219.68,1000,0,776.14,0,500S226.86,0,498.46,0 C775.45,0,1000,223.86,1000,500 Z;
					
					M 1000,500c0,276.14-224.55,500-501.54,500c0-86,1.54-223.86,1.54-500s-1.54-380-1.54-500 C775.45,0,1000,223.86,1000,500 Z;                    
					
					M 1000,500c0,276.14-224.55,500-501.54,500c57.4-53.48,236.4-223.86,236.4-500 S565.08,53.48,498.46,0C775.45,0,1000,223.86,1000,500 Z;"
			/>
		</path>
	</svg>
</a>

CSS

body {
	overflow: hidden;
	background-color: #111;
}

/* Moon button container */
#moonBTN {
	display: block;
	width: 20%;
	margin:100px auto 0 auto;
	cursor: pointer;
}

/* SVG element */
#moon {
	transform: rotate(30deg);
}

JavaScript

// Create handle to SVG animation element and button container
let anim = document.getElementById("moonAnim");
let btn = document.getElementById("moonBTN");

// Listen for click on button element
btn.addEventListener('click', function(e) {
	// Prevent default action (ie loading another page if element is link)
	e.preventDefault();
	// Start animation
	anim.beginElement();
}, false);

// Listen for animation end
anim.addEventListener('endEvent', function(e) {
	// Load page when animation ends. URL extracted from btn link
	//window.location.href = btn.getAttribute('href');
}, false);