Last active
November 7, 2021 17:20
-
-
Save justMoritz/a2e701302597db8eedc42f144f33a2b3 to your computer and use it in GitHub Desktop.
Animated SVG Pipeline
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This function will attempt to inline an SVG to be animated automatically: | |
* for example to write names, trace drawings, etc. | |
* The SVG can come straight from Illustrator as long as two criteria are met: | |
* 1.) The original Artwork. This can be a any combination of paths and polygons | |
* BUT requires all to be in the same group/layer (NO SUBGROUPS, SAME LEVEL!) | |
* This group needs to be named `animationmask` | |
* 2.) A custom drawn path that roughly follows the lines of the mask. This needs to | |
* be a single, continuous path, and put inside a group/layer named `animationpath` | |
* | |
*/ | |
function get_animated_svg_or_img($id, $class = null, $preserveAspectRatioString = null) { | |
// generates random number to ensure unique IDs | |
$randomnum = rand(10,1000); | |
$randomnum = 'r'.$randomnum; | |
// will attempt to inline the SVG, but will print an image as fallback just in case | |
$animatedStringPrint = get_img_or_inline_svg($id, $class, $preserveAspectRatioString); | |
// adds additional styles to the style tag. Requires style tag to be present. | |
$animatedStringPrint = | |
str_replace( | |
'</style>', | |
'#animationpath{ | |
clip-path: url(#'.$randomnum.'animationpathline); | |
} | |
#animationpath path{ | |
fill: none; | |
stroke: #000; | |
stroke-linecap: round; | |
stroke-linejoin:round; | |
stroke-miterlimit:10; | |
stroke-dasharray: 100000; | |
stroke-dashoffset: 100000; | |
stroke-width: 50; | |
animation: svgdrawanimation 8s linear forwards; | |
} | |
@keyframes svgdrawanimation { | |
20% { stroke-width: 50;} | |
100% { stroke-width: 100; stroke-dashoffset: 0;} | |
} | |
</style>', | |
$animatedStringPrint | |
); | |
// turns the animationmask group into a clipPath | |
$animatedStringPrint = | |
str_replace( | |
'<g id="animationmask">', | |
'<defs><clipPath id="'.$randomnum.'animationpathline">', | |
$animatedStringPrint | |
); | |
$animatedStringPrint = preg_replace('/<\/g>\s*<g id=(?:\'|\")animationpath(?:\'|\")>/', "</defs></clipPath><g id='animationpath'>", $animatedStringPrint); | |
// adss a class to the path for external addressing | |
$animatedStringPrint = | |
str_replace( | |
'id=\'animationpath\'', | |
'id="animationpath" class="animationclass"', | |
$animatedStringPrint | |
); | |
// randomizes all instances of animationpath | |
$animatedStringPrint = | |
str_replace( | |
'animationpath', | |
$randomnum.'animationpath', | |
$animatedStringPrint | |
); | |
// returns the final markup | |
return $animatedStringPrint; | |
} | |
/** | |
* Returns either Markup for an Inline SVG, or an image tag based on what it was passed | |
* | |
* @param string $id The ID of the attachment from WP | |
* @param string $class Additional Classes to be printed in the string | |
* @param string $preserveAspectRatioString preserveAspectRatioString | |
* @return Returns the Image or SVG Markup | |
*/ | |
function get_img_or_inline_svg($id, $class = null, $preserveAspectRatioString = null) { | |
$file_type = \wp_check_filetype(get_attached_file($id)); | |
if($file_type['type'] !== 'image/svg+xml'){ | |
if($class){ | |
$printclass = 'class="'.$class.'"'; | |
}else{ | |
$printclass = ''; | |
} | |
return '<img '.$printclass.' src="'.wp_get_attachment_url($id).'" alt="" />'; | |
} | |
else{ | |
return get_inline_svg_html5(file_get_contents(get_attached_file($id)), $class, $preserveAspectRatioString); | |
} | |
} | |
/** | |
* Gets inline svg html5 Description | |
* | |
* @param $svg_content The SVG content passed from the function invoking or directly | |
* @param string $class Additional Classes to be printed | |
* @param string $preserveAspectRatioString preserveAspectRatioString | |
* @param boolean $removeNsElements removeNsElements | |
* @return Returns the Markup | |
*/ | |
function get_inline_svg_html5($svg_content, $class = null, $preserveAspectRatioString = null, $removeNsElements = true) { | |
$sxe=new \SimpleXMLElement($svg_content); | |
$dom_sxe = dom_import_simplexml($sxe); | |
$dom = new \DOMDocument('1.0'); | |
$dom_sxe = $dom->importNode($dom_sxe, true); | |
$dom_sxe = $dom->appendChild($dom_sxe); | |
$element = $dom->childNodes->item(0); | |
$element->removeAttribute('id'); | |
$viewBox = $element->getAttribute('viewBox'); | |
if ($viewBox) { | |
$width = $element->getAttribute('width'); | |
$height = $element->getAttribute('height'); | |
$viewBoxArr = explode(' ', $viewBox); | |
if (!$width) { | |
$element->setAttribute('width', $viewBoxArr[2] - $viewBoxArr[0]); | |
} | |
if (!$height) { | |
$element->setAttribute('height', $viewBoxArr[3] - $viewBoxArr[1]); | |
} | |
} | |
if ($preserveAspectRatioString) { | |
$element->setAttribute('preserveAspectRatio', $preserveAspectRatioString); | |
} | |
if ($class) { | |
$class_attr = $dom->createAttribute('class'); | |
$class_attr->value = $class; | |
$element->appendChild($class_attr); | |
} | |
if ($removeNsElements) { | |
$rootElement = $sxe->getNamespaces(true); | |
array_walk($rootElement, function($uri, $name) use($element) { $element->removeAttributeNS($uri, $name); }); | |
} | |
return $dom->saveXML($dom->documentElement); | |
} | |
?> | |
<script> | |
/** | |
* JavaScript/jQuery: | |
* | |
* Reads the pathlength of a given jQuery selector | |
* and sets the CSS attributes to that exact lenght | |
* | |
* @param {[type]} $path jQuery Object (OF THE PATH!!) | |
*/ | |
var _determine_path_lengh = function($path){ | |
var path = $path.get(0); | |
var pathLen = path.getTotalLength(); | |
$path.css('stroke-dasharray', pathLen); | |
$path.css('stroke-dashoffset', pathLen); | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment