Skip to content

Instantly share code, notes, and snippets.

@tomgp
Last active November 10, 2017 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomgp/0a54da7de1a2a7b29dcfd2645ffcd499 to your computer and use it in GitHub Desktop.
Save tomgp/0a54da7de1a2a7b29dcfd2645ffcd499 to your computer and use it in GitHub Desktop.
svg path jittering
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="path-data-polyfill.js"></script>
<title>Displacement</title>
<style>
.logo{
width:100%;
height:100%;
}
.underlay{
fill: #000;
}
.cyan{
fill: #00ffff;
mix-blend-mode: multiply;
}
.magenta{
fill: #ff00ff;
mix-blend-mode: multiply;
}
.yellow{
fill: #ffff00;
mix-blend-mode: multiply;
}
</style>
</head>
<body>
<svg class="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 351.58 90.02">
<title>vogue-logo</title>
<path id="" class="cyan malleable" data-name="british vogue" d="M288.27,88.17a2.27,2.27,0,0,1-.1-0.41c0-.2.1-0.3,0.1-0.51h6.32c0.71,0,1-.2,1-0.51V3.89a0.75,0.75,0,0,0-.91-0.54l-0.09,0h-14c-0.61-.1-0.92.1-0.92,0.51V66.56c0.1,7.95-2.65,14.06-7.85,18.24A24.64,24.64,0,0,1,256.68,90h-0.1c-21.3.1-31.89-9-31.89-27.21V4.5a1.26,1.26,0,0,0-1.63-1.12h-6.73a0.49,0.49,0,0,1-.1-0.51,0.62,0.62,0,0,1,.1-0.41h31.59a1.09,1.09,0,0,1,0,.92H241.2c-1.43-.1-2,0.31-2,1.22V70.94q0,7.8,4.28,12.84c3.16,3.57,7.54,5.4,13.14,5.3a24.05,24.05,0,0,0,14.67-5c5.09-4.08,7.64-10,7.54-17.53V3.89c0-.41-0.31-0.51-0.92-0.51h-8.76a0.56,0.56,0,0,1-.2-0.51,1.41,1.41,0,0,1,.2-0.41h80.4V33.55a0.51,0.51,0,0,1-.61,0,35,35,0,0,0-3.16-15.18q-6.72-15-24.15-15H311.2c-0.71-.1-1,0.1-1,0.51V42.72c0,0.41.3,0.61,1,.61h3.46c6.83-.1,11.51-2.85,13.76-8.46a17.46,17.46,0,0,0,1.43-8.46,0.49,0.49,0,0,1,.41-0.1c0.1,0,.2.1,0.31,0.1V61.47a0.2,0.2,0,0,1-.4,0A23.06,23.06,0,0,0,328,52.7c-2.75-5.71-7.34-8.56-13.76-8.46h-3c-0.71-.1-1,0.1-1,0.51V86.53c0,0.31.3,0.51,1,.61h10c12.53,0,21.2-5.3,26.09-16a38.81,38.81,0,0,0,3.46-16.3,0.86,0.86,0,0,1,.82,0V88.17h-63.3ZM74.69,3.39H68.58A3,3,0,0,0,67,3.7a1.68,1.68,0,0,0-.41,1.12C66.44,5,57.47,33,39.64,88.57L39.33,88Q33.07,69.62,20.48,36C13.25,16.43,9.48,6,9.07,4.81a2.14,2.14,0,0,0-.61-1.22,0.88,0.88,0,0,0-.81-0.2H0.2A0.41,0.41,0,0,1,0,3,0.56,0.56,0,0,1,.2,2.47H31.08a1.4,1.4,0,0,1,.2.41,1.08,1.08,0,0,1-.2.51H24.76c-1.22-.1-1.63.2-1.32,0.92,0.1,0.1,7.34,20,21.91,59.61a1.66,1.66,0,0,0,.71,1.22Q65.32,5.37,65.42,5.32L65.73,4.2a0.68,0.68,0,0,0-.53-0.8H58.08a1.09,1.09,0,0,1,0-.92H74.69a1.09,1.09,0,0,1,0,.92h0Zm61.55,58.9a48.64,48.64,0,0,1-8.66,14.27,42.62,42.62,0,0,1-12,9.58A29.42,29.42,0,0,1,102,89.59,30.34,30.34,0,0,1,87.94,86a37.74,37.74,0,0,1-11.82-9.58,46.42,46.42,0,0,1-8-14.16A50.16,50.16,0,0,1,65,44.86,49.11,49.11,0,0,1,76.53,13.68,38.48,38.48,0,0,1,88.55,4,27.46,27.46,0,0,1,102.31.43,30,30,0,0,1,116,3.79a37.41,37.41,0,0,1,12,9.27c7.85,8.66,11.72,19.36,11.62,31.79a46.12,46.12,0,0,1-3.36,17.42h0Zm-16.3-48.1Q114.74,1,102.2,1C87.84,1,81.63,15.61,81.63,44.45c0,14.78.19,25.27,2.64,31.59,3.16,8.56,9.17,12.84,18.14,12.84,8.25,0,14.16-4.38,17.53-13.25q4-10.4,4.08-31.18c-0.1-13.35-1.43-23.54-4.08-30.26h0ZM197.79,52.7h-7a0.53,0.53,0,0,1-.2-0.41,0.77,0.77,0,0,1,.2-0.41h30.06c0,0.1.1,0.31,0.1,0.41a4.51,4.51,0,0,1-.1.51h-6.62c-0.61-.1-0.92.1-0.92,0.51V88.06c0,0.31-.2.41-0.41,0.2-0.2-1.43-1.22-2.75-3-4-2.14-1.43-4.89-1.63-8-.61A46.54,46.54,0,0,0,195,86.2l-4.48,1.94a22.55,22.55,0,0,1-9.78,1.43,27.43,27.43,0,0,1-12.84-3.77A36,36,0,0,1,157,76.45Q146.79,63.3,146.94,45.27a50.42,50.42,0,0,1,3.36-17.53,52.58,52.58,0,0,1,8.36-14.47,38.68,38.68,0,0,1,11.11-9.88c4.07-2.39,8-3.57,11.81-3.39a23.4,23.4,0,0,1,8.05,1.53l6.11,2.24a10.43,10.43,0,0,0,5.4.61A12.28,12.28,0,0,0,206.86.84a1.22,1.22,0,0,1,.51-0.51c0.2-.31.41-0.31,0.51-0.1l-0.1,30.26c0,0.31-.2.41-0.61,0.2l-1.32-5a52.23,52.23,0,0,0-3.87-10C197,6.14,190.55,1.14,182.4.84c-7.44-.41-12.84,3.77-16,12.63-2.65,7.24-3.87,17.53-3.77,31.18q0.3,42.19,16.61,44a24.45,24.45,0,0,0,11.62-1.53q8.25-3.67,8.25-13.66V53.21c0-.41-0.41-0.51-1.33-0.51h0Z" transform="translate(0.01 0.02)"></path>
<path id="" class="magenta malleable" data-name="british vogue" d="M288.27,88.17a2.27,2.27,0,0,1-.1-0.41c0-.2.1-0.3,0.1-0.51h6.32c0.71,0,1-.2,1-0.51V3.89a0.75,0.75,0,0,0-.91-0.54l-0.09,0h-14c-0.61-.1-0.92.1-0.92,0.51V66.56c0.1,7.95-2.65,14.06-7.85,18.24A24.64,24.64,0,0,1,256.68,90h-0.1c-21.3.1-31.89-9-31.89-27.21V4.5a1.26,1.26,0,0,0-1.63-1.12h-6.73a0.49,0.49,0,0,1-.1-0.51,0.62,0.62,0,0,1,.1-0.41h31.59a1.09,1.09,0,0,1,0,.92H241.2c-1.43-.1-2,0.31-2,1.22V70.94q0,7.8,4.28,12.84c3.16,3.57,7.54,5.4,13.14,5.3a24.05,24.05,0,0,0,14.67-5c5.09-4.08,7.64-10,7.54-17.53V3.89c0-.41-0.31-0.51-0.92-0.51h-8.76a0.56,0.56,0,0,1-.2-0.51,1.41,1.41,0,0,1,.2-0.41h80.4V33.55a0.51,0.51,0,0,1-.61,0,35,35,0,0,0-3.16-15.18q-6.72-15-24.15-15H311.2c-0.71-.1-1,0.1-1,0.51V42.72c0,0.41.3,0.61,1,.61h3.46c6.83-.1,11.51-2.85,13.76-8.46a17.46,17.46,0,0,0,1.43-8.46,0.49,0.49,0,0,1,.41-0.1c0.1,0,.2.1,0.31,0.1V61.47a0.2,0.2,0,0,1-.4,0A23.06,23.06,0,0,0,328,52.7c-2.75-5.71-7.34-8.56-13.76-8.46h-3c-0.71-.1-1,0.1-1,0.51V86.53c0,0.31.3,0.51,1,.61h10c12.53,0,21.2-5.3,26.09-16a38.81,38.81,0,0,0,3.46-16.3,0.86,0.86,0,0,1,.82,0V88.17h-63.3ZM74.69,3.39H68.58A3,3,0,0,0,67,3.7a1.68,1.68,0,0,0-.41,1.12C66.44,5,57.47,33,39.64,88.57L39.33,88Q33.07,69.62,20.48,36C13.25,16.43,9.48,6,9.07,4.81a2.14,2.14,0,0,0-.61-1.22,0.88,0.88,0,0,0-.81-0.2H0.2A0.41,0.41,0,0,1,0,3,0.56,0.56,0,0,1,.2,2.47H31.08a1.4,1.4,0,0,1,.2.41,1.08,1.08,0,0,1-.2.51H24.76c-1.22-.1-1.63.2-1.32,0.92,0.1,0.1,7.34,20,21.91,59.61a1.66,1.66,0,0,0,.71,1.22Q65.32,5.37,65.42,5.32L65.73,4.2a0.68,0.68,0,0,0-.53-0.8H58.08a1.09,1.09,0,0,1,0-.92H74.69a1.09,1.09,0,0,1,0,.92h0Zm61.55,58.9a48.64,48.64,0,0,1-8.66,14.27,42.62,42.62,0,0,1-12,9.58A29.42,29.42,0,0,1,102,89.59,30.34,30.34,0,0,1,87.94,86a37.74,37.74,0,0,1-11.82-9.58,46.42,46.42,0,0,1-8-14.16A50.16,50.16,0,0,1,65,44.86,49.11,49.11,0,0,1,76.53,13.68,38.48,38.48,0,0,1,88.55,4,27.46,27.46,0,0,1,102.31.43,30,30,0,0,1,116,3.79a37.41,37.41,0,0,1,12,9.27c7.85,8.66,11.72,19.36,11.62,31.79a46.12,46.12,0,0,1-3.36,17.42h0Zm-16.3-48.1Q114.74,1,102.2,1C87.84,1,81.63,15.61,81.63,44.45c0,14.78.19,25.27,2.64,31.59,3.16,8.56,9.17,12.84,18.14,12.84,8.25,0,14.16-4.38,17.53-13.25q4-10.4,4.08-31.18c-0.1-13.35-1.43-23.54-4.08-30.26h0ZM197.79,52.7h-7a0.53,0.53,0,0,1-.2-0.41,0.77,0.77,0,0,1,.2-0.41h30.06c0,0.1.1,0.31,0.1,0.41a4.51,4.51,0,0,1-.1.51h-6.62c-0.61-.1-0.92.1-0.92,0.51V88.06c0,0.31-.2.41-0.41,0.2-0.2-1.43-1.22-2.75-3-4-2.14-1.43-4.89-1.63-8-.61A46.54,46.54,0,0,0,195,86.2l-4.48,1.94a22.55,22.55,0,0,1-9.78,1.43,27.43,27.43,0,0,1-12.84-3.77A36,36,0,0,1,157,76.45Q146.79,63.3,146.94,45.27a50.42,50.42,0,0,1,3.36-17.53,52.58,52.58,0,0,1,8.36-14.47,38.68,38.68,0,0,1,11.11-9.88c4.07-2.39,8-3.57,11.81-3.39a23.4,23.4,0,0,1,8.05,1.53l6.11,2.24a10.43,10.43,0,0,0,5.4.61A12.28,12.28,0,0,0,206.86.84a1.22,1.22,0,0,1,.51-0.51c0.2-.31.41-0.31,0.51-0.1l-0.1,30.26c0,0.31-.2.41-0.61,0.2l-1.32-5a52.23,52.23,0,0,0-3.87-10C197,6.14,190.55,1.14,182.4.84c-7.44-.41-12.84,3.77-16,12.63-2.65,7.24-3.87,17.53-3.77,31.18q0.3,42.19,16.61,44a24.45,24.45,0,0,0,11.62-1.53q8.25-3.67,8.25-13.66V53.21c0-.41-0.41-0.51-1.33-0.51h0Z" transform="translate(0.01 0.02)"></path>
<path id="british_vogue" class="yellow malleable" data-name="british vogue" d="M288.27,88.17a2.27,2.27,0,0,1-.1-0.41c0-.2.1-0.3,0.1-0.51h6.32c0.71,0,1-.2,1-0.51V3.89a0.75,0.75,0,0,0-.91-0.54l-0.09,0h-14c-0.61-.1-0.92.1-0.92,0.51V66.56c0.1,7.95-2.65,14.06-7.85,18.24A24.64,24.64,0,0,1,256.68,90h-0.1c-21.3.1-31.89-9-31.89-27.21V4.5a1.26,1.26,0,0,0-1.63-1.12h-6.73a0.49,0.49,0,0,1-.1-0.51,0.62,0.62,0,0,1,.1-0.41h31.59a1.09,1.09,0,0,1,0,.92H241.2c-1.43-.1-2,0.31-2,1.22V70.94q0,7.8,4.28,12.84c3.16,3.57,7.54,5.4,13.14,5.3a24.05,24.05,0,0,0,14.67-5c5.09-4.08,7.64-10,7.54-17.53V3.89c0-.41-0.31-0.51-0.92-0.51h-8.76a0.56,0.56,0,0,1-.2-0.51,1.41,1.41,0,0,1,.2-0.41h80.4V33.55a0.51,0.51,0,0,1-.61,0,35,35,0,0,0-3.16-15.18q-6.72-15-24.15-15H311.2c-0.71-.1-1,0.1-1,0.51V42.72c0,0.41.3,0.61,1,.61h3.46c6.83-.1,11.51-2.85,13.76-8.46a17.46,17.46,0,0,0,1.43-8.46,0.49,0.49,0,0,1,.41-0.1c0.1,0,.2.1,0.31,0.1V61.47a0.2,0.2,0,0,1-.4,0A23.06,23.06,0,0,0,328,52.7c-2.75-5.71-7.34-8.56-13.76-8.46h-3c-0.71-.1-1,0.1-1,0.51V86.53c0,0.31.3,0.51,1,.61h10c12.53,0,21.2-5.3,26.09-16a38.81,38.81,0,0,0,3.46-16.3,0.86,0.86,0,0,1,.82,0V88.17h-63.3ZM74.69,3.39H68.58A3,3,0,0,0,67,3.7a1.68,1.68,0,0,0-.41,1.12C66.44,5,57.47,33,39.64,88.57L39.33,88Q33.07,69.62,20.48,36C13.25,16.43,9.48,6,9.07,4.81a2.14,2.14,0,0,0-.61-1.22,0.88,0.88,0,0,0-.81-0.2H0.2A0.41,0.41,0,0,1,0,3,0.56,0.56,0,0,1,.2,2.47H31.08a1.4,1.4,0,0,1,.2.41,1.08,1.08,0,0,1-.2.51H24.76c-1.22-.1-1.63.2-1.32,0.92,0.1,0.1,7.34,20,21.91,59.61a1.66,1.66,0,0,0,.71,1.22Q65.32,5.37,65.42,5.32L65.73,4.2a0.68,0.68,0,0,0-.53-0.8H58.08a1.09,1.09,0,0,1,0-.92H74.69a1.09,1.09,0,0,1,0,.92h0Zm61.55,58.9a48.64,48.64,0,0,1-8.66,14.27,42.62,42.62,0,0,1-12,9.58A29.42,29.42,0,0,1,102,89.59,30.34,30.34,0,0,1,87.94,86a37.74,37.74,0,0,1-11.82-9.58,46.42,46.42,0,0,1-8-14.16A50.16,50.16,0,0,1,65,44.86,49.11,49.11,0,0,1,76.53,13.68,38.48,38.48,0,0,1,88.55,4,27.46,27.46,0,0,1,102.31.43,30,30,0,0,1,116,3.79a37.41,37.41,0,0,1,12,9.27c7.85,8.66,11.72,19.36,11.62,31.79a46.12,46.12,0,0,1-3.36,17.42h0Zm-16.3-48.1Q114.74,1,102.2,1C87.84,1,81.63,15.61,81.63,44.45c0,14.78.19,25.27,2.64,31.59,3.16,8.56,9.17,12.84,18.14,12.84,8.25,0,14.16-4.38,17.53-13.25q4-10.4,4.08-31.18c-0.1-13.35-1.43-23.54-4.08-30.26h0ZM197.79,52.7h-7a0.53,0.53,0,0,1-.2-0.41,0.77,0.77,0,0,1,.2-0.41h30.06c0,0.1.1,0.31,0.1,0.41a4.51,4.51,0,0,1-.1.51h-6.62c-0.61-.1-0.92.1-0.92,0.51V88.06c0,0.31-.2.41-0.41,0.2-0.2-1.43-1.22-2.75-3-4-2.14-1.43-4.89-1.63-8-.61A46.54,46.54,0,0,0,195,86.2l-4.48,1.94a22.55,22.55,0,0,1-9.78,1.43,27.43,27.43,0,0,1-12.84-3.77A36,36,0,0,1,157,76.45Q146.79,63.3,146.94,45.27a50.42,50.42,0,0,1,3.36-17.53,52.58,52.58,0,0,1,8.36-14.47,38.68,38.68,0,0,1,11.11-9.88c4.07-2.39,8-3.57,11.81-3.39a23.4,23.4,0,0,1,8.05,1.53l6.11,2.24a10.43,10.43,0,0,0,5.4.61A12.28,12.28,0,0,0,206.86.84a1.22,1.22,0,0,1,.51-0.51c0.2-.31.41-0.31,0.51-0.1l-0.1,30.26c0,0.31-.2.41-0.61,0.2l-1.32-5a52.23,52.23,0,0,0-3.87-10C197,6.14,190.55,1.14,182.4.84c-7.44-.41-12.84,3.77-16,12.63-2.65,7.24-3.87,17.53-3.77,31.18q0.3,42.19,16.61,44a24.45,24.45,0,0,0,11.62-1.53q8.25-3.67,8.25-13.66V53.21c0-.41-0.41-0.51-1.33-0.51h0Z" transform="translate(0.01 0.02)"></path>
<path id="reference" class="underlay" data-name="british vogue" d="M288.27,88.17a2.27,2.27,0,0,1-.1-0.41c0-.2.1-0.3,0.1-0.51h6.32c0.71,0,1-.2,1-0.51V3.89a0.75,0.75,0,0,0-.91-0.54l-0.09,0h-14c-0.61-.1-0.92.1-0.92,0.51V66.56c0.1,7.95-2.65,14.06-7.85,18.24A24.64,24.64,0,0,1,256.68,90h-0.1c-21.3.1-31.89-9-31.89-27.21V4.5a1.26,1.26,0,0,0-1.63-1.12h-6.73a0.49,0.49,0,0,1-.1-0.51,0.62,0.62,0,0,1,.1-0.41h31.59a1.09,1.09,0,0,1,0,.92H241.2c-1.43-.1-2,0.31-2,1.22V70.94q0,7.8,4.28,12.84c3.16,3.57,7.54,5.4,13.14,5.3a24.05,24.05,0,0,0,14.67-5c5.09-4.08,7.64-10,7.54-17.53V3.89c0-.41-0.31-0.51-0.92-0.51h-8.76a0.56,0.56,0,0,1-.2-0.51,1.41,1.41,0,0,1,.2-0.41h80.4V33.55a0.51,0.51,0,0,1-.61,0,35,35,0,0,0-3.16-15.18q-6.72-15-24.15-15H311.2c-0.71-.1-1,0.1-1,0.51V42.72c0,0.41.3,0.61,1,.61h3.46c6.83-.1,11.51-2.85,13.76-8.46a17.46,17.46,0,0,0,1.43-8.46,0.49,0.49,0,0,1,.41-0.1c0.1,0,.2.1,0.31,0.1V61.47a0.2,0.2,0,0,1-.4,0A23.06,23.06,0,0,0,328,52.7c-2.75-5.71-7.34-8.56-13.76-8.46h-3c-0.71-.1-1,0.1-1,0.51V86.53c0,0.31.3,0.51,1,.61h10c12.53,0,21.2-5.3,26.09-16a38.81,38.81,0,0,0,3.46-16.3,0.86,0.86,0,0,1,.82,0V88.17h-63.3ZM74.69,3.39H68.58A3,3,0,0,0,67,3.7a1.68,1.68,0,0,0-.41,1.12C66.44,5,57.47,33,39.64,88.57L39.33,88Q33.07,69.62,20.48,36C13.25,16.43,9.48,6,9.07,4.81a2.14,2.14,0,0,0-.61-1.22,0.88,0.88,0,0,0-.81-0.2H0.2A0.41,0.41,0,0,1,0,3,0.56,0.56,0,0,1,.2,2.47H31.08a1.4,1.4,0,0,1,.2.41,1.08,1.08,0,0,1-.2.51H24.76c-1.22-.1-1.63.2-1.32,0.92,0.1,0.1,7.34,20,21.91,59.61a1.66,1.66,0,0,0,.71,1.22Q65.32,5.37,65.42,5.32L65.73,4.2a0.68,0.68,0,0,0-.53-0.8H58.08a1.09,1.09,0,0,1,0-.92H74.69a1.09,1.09,0,0,1,0,.92h0Zm61.55,58.9a48.64,48.64,0,0,1-8.66,14.27,42.62,42.62,0,0,1-12,9.58A29.42,29.42,0,0,1,102,89.59,30.34,30.34,0,0,1,87.94,86a37.74,37.74,0,0,1-11.82-9.58,46.42,46.42,0,0,1-8-14.16A50.16,50.16,0,0,1,65,44.86,49.11,49.11,0,0,1,76.53,13.68,38.48,38.48,0,0,1,88.55,4,27.46,27.46,0,0,1,102.31.43,30,30,0,0,1,116,3.79a37.41,37.41,0,0,1,12,9.27c7.85,8.66,11.72,19.36,11.62,31.79a46.12,46.12,0,0,1-3.36,17.42h0Zm-16.3-48.1Q114.74,1,102.2,1C87.84,1,81.63,15.61,81.63,44.45c0,14.78.19,25.27,2.64,31.59,3.16,8.56,9.17,12.84,18.14,12.84,8.25,0,14.16-4.38,17.53-13.25q4-10.4,4.08-31.18c-0.1-13.35-1.43-23.54-4.08-30.26h0ZM197.79,52.7h-7a0.53,0.53,0,0,1-.2-0.41,0.77,0.77,0,0,1,.2-0.41h30.06c0,0.1.1,0.31,0.1,0.41a4.51,4.51,0,0,1-.1.51h-6.62c-0.61-.1-0.92.1-0.92,0.51V88.06c0,0.31-.2.41-0.41,0.2-0.2-1.43-1.22-2.75-3-4-2.14-1.43-4.89-1.63-8-.61A46.54,46.54,0,0,0,195,86.2l-4.48,1.94a22.55,22.55,0,0,1-9.78,1.43,27.43,27.43,0,0,1-12.84-3.77A36,36,0,0,1,157,76.45Q146.79,63.3,146.94,45.27a50.42,50.42,0,0,1,3.36-17.53,52.58,52.58,0,0,1,8.36-14.47,38.68,38.68,0,0,1,11.11-9.88c4.07-2.39,8-3.57,11.81-3.39a23.4,23.4,0,0,1,8.05,1.53l6.11,2.24a10.43,10.43,0,0,0,5.4.61A12.28,12.28,0,0,0,206.86.84a1.22,1.22,0,0,1,.51-0.51c0.2-.31.41-0.31,0.51-0.1l-0.1,30.26c0,0.31-.2.41-0.61,0.2l-1.32-5a52.23,52.23,0,0,0-3.87-10C197,6.14,190.55,1.14,182.4.84c-7.44-.41-12.84,3.77-16,12.63-2.65,7.24-3.87,17.53-3.77,31.18q0.3,42.19,16.61,44a24.45,24.45,0,0,0,11.62-1.53q8.25-3.67,8.25-13.66V53.21c0-.41-0.41-0.51-1.33-0.51h0Z" transform="translate(0.01 0.02)"></path>
</svg>
</body>
<script>
const originalPathString = d3.select('path#reference').attr('d');
const xyJitterElement = (e)=>{
if(e.values.length > 0){
e.values[0] += Math.random()*10 - 5;
if(e.values.length > 1){
e.values[1] += Math.random()*10 - 5;
if(e.values.length > 2){
e.values[2] += Math.random()*10 - 5;
}
}
}
return e;
}
const jitter = () => {
d3.selectAll('path.malleable')
.each(function(){
const duplicatePathNode = d3.select('path#reference').node().cloneNode();
const newPathData = duplicatePathNode
.getPathData()
.map(xyJitterElement);
duplicatePathNode.setPathData(newPathData);
const newPathString = d3.select(duplicatePathNode).attr('d')
d3.select(this)
.transition()
.attr('d', newPathString);
});
}
const restore = () => {
d3.selectAll('path.malleable')
.transition()
.attr('d', originalPathString);
}
d3.select('svg')
.on('mouseover',jitter)
.on('mouseout',restore)
</script>
</html>
// @info
// Polyfill for SVG getPathData() and setPathData() methods. Based on:
// - SVGPathSeg polyfill by Philip Rogers (MIT License)
// https://github.com/progers/pathseg
// - SVGPathNormalizer by Tadahisa Motooka (MIT License)
// https://github.com/motooka/SVGPathNormalizer/tree/master/src
// - arcToCubicCurves() by Dmitry Baranovskiy (MIT License)
// https://github.com/DmitryBaranovskiy/raphael/blob/v2.1.1/raphael.core.js#L1837
// @author
// Jarosław Foksa
// @license
// MIT License
if (!SVGPathElement.prototype.getPathData || !SVGPathElement.prototype.setPathData) {
(function() {
var commandsMap = {
"Z":"Z", "M":"M", "L":"L", "C":"C", "Q":"Q", "A":"A", "H":"H", "V":"V", "S":"S", "T":"T",
"z":"Z", "m":"m", "l":"l", "c":"c", "q":"q", "a":"a", "h":"h", "v":"v", "s":"s", "t":"t"
};
var Source = function(string) {
this._string = string;
this._currentIndex = 0;
this._endIndex = this._string.length;
this._prevCommand = null;
this._skipOptionalSpaces();
};
var isIE = window.navigator.userAgent.indexOf("MSIE ") !== -1;
Source.prototype = {
parseSegment: function() {
var char = this._string[this._currentIndex];
var command = commandsMap[char] ? commandsMap[char] : null;
if (command === null) {
// Possibly an implicit command. Not allowed if this is the first command.
if (this._prevCommand === null) {
return null;
}
// Check for remaining coordinates in the current command.
if (
(char === "+" || char === "-" || char === "." || (char >= "0" && char <= "9")) && this._prevCommand !== "Z"
) {
if (this._prevCommand === "M") {
command = "L";
}
else if (this._prevCommand === "m") {
command = "l";
}
else {
command = this._prevCommand;
}
}
else {
command = null;
}
if (command === null) {
return null;
}
}
else {
this._currentIndex += 1;
}
this._prevCommand = command;
var values = null;
var cmd = command.toUpperCase();
if (cmd === "H" || cmd === "V") {
values = [this._parseNumber()];
}
else if (cmd === "M" || cmd === "L" || cmd === "T") {
values = [this._parseNumber(), this._parseNumber()];
}
else if (cmd === "S" || cmd === "Q") {
values = [this._parseNumber(), this._parseNumber(), this._parseNumber(), this._parseNumber()];
}
else if (cmd === "C") {
values = [
this._parseNumber(),
this._parseNumber(),
this._parseNumber(),
this._parseNumber(),
this._parseNumber(),
this._parseNumber()
];
}
else if (cmd === "A") {
values = [
this._parseNumber(),
this._parseNumber(),
this._parseNumber(),
this._parseArcFlag(),
this._parseArcFlag(),
this._parseNumber(),
this._parseNumber()
];
}
else if (cmd === "Z") {
this._skipOptionalSpaces();
values = [];
}
if (values === null || values.indexOf(null) >= 0) {
// Unknown command or known command with invalid values
return null;
}
else {
return {type: command, values: values};
}
},
hasMoreData: function() {
return this._currentIndex < this._endIndex;
},
peekSegmentType: function() {
var char = this._string[this._currentIndex];
return commandsMap[char] ? commandsMap[char] : null;
},
initialCommandIsMoveTo: function() {
// If the path is empty it is still valid, so return true.
if (!this.hasMoreData()) {
return true;
}
var command = this.peekSegmentType();
// Path must start with moveTo.
return command === "M" || command === "m";
},
_isCurrentSpace: function() {
var char = this._string[this._currentIndex];
return char <= " " && (char === " " || char === "\n" || char === "\t" || char === "\r" || char === "\f");
},
_skipOptionalSpaces: function() {
while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {
this._currentIndex += 1;
}
return this._currentIndex < this._endIndex;
},
_skipOptionalSpacesOrDelimiter: function() {
if (
this._currentIndex < this._endIndex &&
!this._isCurrentSpace() &&
this._string[this._currentIndex] !== ","
) {
return false;
}
if (this._skipOptionalSpaces()) {
if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === ",") {
this._currentIndex += 1;
this._skipOptionalSpaces();
}
}
return this._currentIndex < this._endIndex;
},
// Parse a number from an SVG path. This very closely follows genericParseNumber(...) from
// Source/core/svg/SVGParserUtilities.cpp.
// Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
_parseNumber: function() {
var exponent = 0;
var integer = 0;
var frac = 1;
var decimal = 0;
var sign = 1;
var expsign = 1;
var startIndex = this._currentIndex;
this._skipOptionalSpaces();
// Read the sign.
if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === "+") {
this._currentIndex += 1;
}
else if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === "-") {
this._currentIndex += 1;
sign = -1;
}
if (
this._currentIndex === this._endIndex ||
(
(this._string[this._currentIndex] < "0" || this._string[this._currentIndex] > "9") &&
this._string[this._currentIndex] !== "."
)
) {
// The first character of a number must be one of [0-9+-.].
return null;
}
// Read the integer part, build right-to-left.
var startIntPartIndex = this._currentIndex;
while (
this._currentIndex < this._endIndex &&
this._string[this._currentIndex] >= "0" &&
this._string[this._currentIndex] <= "9"
) {
this._currentIndex += 1; // Advance to first non-digit.
}
if (this._currentIndex !== startIntPartIndex) {
var scanIntPartIndex = this._currentIndex - 1;
var multiplier = 1;
while (scanIntPartIndex >= startIntPartIndex) {
integer += multiplier * (this._string[scanIntPartIndex] - "0");
scanIntPartIndex -= 1;
multiplier *= 10;
}
}
// Read the decimals.
if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === ".") {
this._currentIndex += 1;
// There must be a least one digit following the .
if (
this._currentIndex >= this._endIndex ||
this._string[this._currentIndex] < "0" ||
this._string[this._currentIndex] > "9"
) {
return null;
}
while (
this._currentIndex < this._endIndex &&
this._string[this._currentIndex] >= "0" &&
this._string[this._currentIndex] <= "9"
) {
frac *= 10;
decimal += (this._string.charAt(this._currentIndex) - "0") / frac;
this._currentIndex += 1;
}
}
// Read the exponent part.
if (
this._currentIndex !== startIndex &&
this._currentIndex + 1 < this._endIndex &&
(this._string[this._currentIndex] === "e" || this._string[this._currentIndex] === "E") &&
(this._string[this._currentIndex + 1] !== "x" && this._string[this._currentIndex + 1] !== "m")
) {
this._currentIndex += 1;
// Read the sign of the exponent.
if (this._string[this._currentIndex] === "+") {
this._currentIndex += 1;
}
else if (this._string[this._currentIndex] === "-") {
this._currentIndex += 1;
expsign = -1;
}
// There must be an exponent.
if (
this._currentIndex >= this._endIndex ||
this._string[this._currentIndex] < "0" ||
this._string[this._currentIndex] > "9"
) {
return null;
}
while (
this._currentIndex < this._endIndex &&
this._string[this._currentIndex] >= "0" &&
this._string[this._currentIndex] <= "9"
) {
exponent *= 10;
exponent += (this._string[this._currentIndex] - "0");
this._currentIndex += 1;
}
}
var number = integer + decimal;
number *= sign;
if (exponent) {
number *= Math.pow(10, expsign * exponent);
}
if (startIndex === this._currentIndex) {
return null;
}
this._skipOptionalSpacesOrDelimiter();
return number;
},
_parseArcFlag: function() {
if (this._currentIndex >= this._endIndex) {
return null;
}
var flag = null;
var flagChar = this._string[this._currentIndex];
this._currentIndex += 1;
if (flagChar === "0") {
flag = 0;
}
else if (flagChar === "1") {
flag = 1;
}
else {
return null;
}
this._skipOptionalSpacesOrDelimiter();
return flag;
}
};
var parsePathDataString = function(string) {
if (!string || string.length === 0) return [];
var source = new Source(string);
var pathData = [];
if (source.initialCommandIsMoveTo()) {
while (source.hasMoreData()) {
var pathSeg = source.parseSegment();
if (pathSeg === null) {
break;
}
else {
pathData.push(pathSeg);
}
}
}
return pathData;
}
var setAttribute = SVGPathElement.prototype.setAttribute;
var removeAttribute = SVGPathElement.prototype.removeAttribute;
var $cachedPathData = window.Symbol ? Symbol() : "__cachedPathData";
var $cachedNormalizedPathData = window.Symbol ? Symbol() : "__cachedNormalizedPathData";
// @info
// Get an array of corresponding cubic bezier curve parameters for given arc curve paramters.
var arcToCubicCurves = function(x1, y1, x2, y2, r1, r2, angle, largeArcFlag, sweepFlag, _recursive) {
var degToRad = function(degrees) {
return (Math.PI * degrees) / 180;
};
var rotate = function(x, y, angleRad) {
var X = x * Math.cos(angleRad) - y * Math.sin(angleRad);
var Y = x * Math.sin(angleRad) + y * Math.cos(angleRad);
return {x: X, y: Y};
};
var angleRad = degToRad(angle);
var params = [];
var f1, f2, cx, cy;
if (_recursive) {
f1 = _recursive[0];
f2 = _recursive[1];
cx = _recursive[2];
cy = _recursive[3];
}
else {
var p1 = rotate(x1, y1, -angleRad);
x1 = p1.x;
y1 = p1.y;
var p2 = rotate(x2, y2, -angleRad);
x2 = p2.x;
y2 = p2.y;
var x = (x1 - x2) / 2;
var y = (y1 - y2) / 2;
var h = (x * x) / (r1 * r1) + (y * y) / (r2 * r2);
if (h > 1) {
h = Math.sqrt(h);
r1 = h * r1;
r2 = h * r2;
}
var sign;
if (largeArcFlag === sweepFlag) {
sign = -1;
}
else {
sign = 1;
}
var r1Pow = r1 * r1;
var r2Pow = r2 * r2;
var left = r1Pow * r2Pow - r1Pow * y * y - r2Pow * x * x;
var right = r1Pow * y * y + r2Pow * x * x;
var k = sign * Math.sqrt(Math.abs(left/right));
cx = k * r1 * y / r2 + (x1 + x2) / 2;
cy = k * -r2 * x / r1 + (y1 + y2) / 2;
f1 = Math.asin(parseFloat(((y1 - cy) / r2).toFixed(9)));
f2 = Math.asin(parseFloat(((y2 - cy) / r2).toFixed(9)));
if (x1 < cx) {
f1 = Math.PI - f1;
}
if (x2 < cx) {
f2 = Math.PI - f2;
}
if (f1 < 0) {
f1 = Math.PI * 2 + f1;
}
if (f2 < 0) {
f2 = Math.PI * 2 + f2;
}
if (sweepFlag && f1 > f2) {
f1 = f1 - Math.PI * 2;
}
if (!sweepFlag && f2 > f1) {
f2 = f2 - Math.PI * 2;
}
}
var df = f2 - f1;
if (Math.abs(df) > (Math.PI * 120 / 180)) {
var f2old = f2;
var x2old = x2;
var y2old = y2;
if (sweepFlag && f2 > f1) {
f2 = f1 + (Math.PI * 120 / 180) * (1);
}
else {
f2 = f1 + (Math.PI * 120 / 180) * (-1);
}
x2 = cx + r1 * Math.cos(f2);
y2 = cy + r2 * Math.sin(f2);
params = arcToCubicCurves(x2, y2, x2old, y2old, r1, r2, angle, 0, sweepFlag, [f2, f2old, cx, cy]);
}
df = f2 - f1;
var c1 = Math.cos(f1);
var s1 = Math.sin(f1);
var c2 = Math.cos(f2);
var s2 = Math.sin(f2);
var t = Math.tan(df / 4);
var hx = 4 / 3 * r1 * t;
var hy = 4 / 3 * r2 * t;
var m1 = [x1, y1];
var m2 = [x1 + hx * s1, y1 - hy * c1];
var m3 = [x2 + hx * s2, y2 - hy * c2];
var m4 = [x2, y2];
m2[0] = 2 * m1[0] - m2[0];
m2[1] = 2 * m1[1] - m2[1];
if (_recursive) {
return [m2, m3, m4].concat(params);
}
else {
params = [m2, m3, m4].concat(params);
var curves = [];
for (var i = 0; i < params.length; i+=3) {
var r1 = rotate(params[i][0], params[i][1], angleRad);
var r2 = rotate(params[i+1][0], params[i+1][1], angleRad);
var r3 = rotate(params[i+2][0], params[i+2][1], angleRad);
curves.push([r1.x, r1.y, r2.x, r2.y, r3.x, r3.y]);
}
return curves;
}
};
var clonePathData = function(pathData) {
return pathData.map( function(seg) {
return {type: seg.type, values: Array.prototype.slice.call(seg.values)}
});
};
// @info
// Takes any path data, returns path data that consists only from absolute commands.
var absolutizePathData = function(pathData) {
var absolutizedPathData = [];
var currentX = null;
var currentY = null;
var subpathX = null;
var subpathY = null;
pathData.forEach( function(seg) {
var type = seg.type;
if (type === "M") {
var x = seg.values[0];
var y = seg.values[1];
absolutizedPathData.push({type: "M", values: [x, y]});
subpathX = x;
subpathY = y;
currentX = x;
currentY = y;
}
else if (type === "m") {
var x = currentX + seg.values[0];
var y = currentY + seg.values[1];
absolutizedPathData.push({type: "M", values: [x, y]});
subpathX = x;
subpathY = y;
currentX = x;
currentY = y;
}
else if (type === "L") {
var x = seg.values[0];
var y = seg.values[1];
absolutizedPathData.push({type: "L", values: [x, y]});
currentX = x;
currentY = y;
}
else if (type === "l") {
var x = currentX + seg.values[0];
var y = currentY + seg.values[1];
absolutizedPathData.push({type: "L", values: [x, y]});
currentX = x;
currentY = y;
}
else if (type === "C") {
var x1 = seg.values[0];
var y1 = seg.values[1];
var x2 = seg.values[2];
var y2 = seg.values[3];
var x = seg.values[4];
var y = seg.values[5];
absolutizedPathData.push({type: "C", values: [x1, y1, x2, y2, x, y]});
currentX = x;
currentY = y;
}
else if (type === "c") {
var x1 = currentX + seg.values[0];
var y1 = currentY + seg.values[1];
var x2 = currentX + seg.values[2];
var y2 = currentY + seg.values[3];
var x = currentX + seg.values[4];
var y = currentY + seg.values[5];
absolutizedPathData.push({type: "C", values: [x1, y1, x2, y2, x, y]});
currentX = x;
currentY = y;
}
else if (type === "Q") {
var x1 = seg.values[0];
var y1 = seg.values[1];
var x = seg.values[2];
var y = seg.values[3];
absolutizedPathData.push({type: "Q", values: [x1, y1, x, y]});
currentX = x;
currentY = y;
}
else if (type === "q") {
var x1 = currentX + seg.values[0];
var y1 = currentY + seg.values[1];
var x = currentX + seg.values[2];
var y = currentY + seg.values[3];
absolutizedPathData.push({type: "Q", values: [x1, y1, x, y]});
currentX = x;
currentY = y;
}
else if (type === "A") {
var x = seg.values[5];
var y = seg.values[6];
absolutizedPathData.push({
type: "A",
values: [seg.values[0], seg.values[1], seg.values[2], seg.values[3], seg.values[4], x, y]
});
currentX = x;
currentY = y;
}
else if (type === "a") {
var x = currentX + seg.values[5];
var y = currentY + seg.values[6];
absolutizedPathData.push({
type: "A",
values: [seg.values[0], seg.values[1], seg.values[2], seg.values[3], seg.values[4], x, y]
});
currentX = x;
currentY = y;
}
else if (type === "H") {
var x = seg.values[0];
absolutizedPathData.push({type: "H", values: [x]});
currentX = x;
}
else if (type === "h") {
var x = currentX + seg.values[0];
absolutizedPathData.push({type: "H", values: [x]});
currentX = x;
}
else if (type === "V") {
var y = seg.values[0];
absolutizedPathData.push({type: "V", values: [y]});
currentY = y;
}
else if (type === "v") {
var y = currentY + seg.values[0];
absolutizedPathData.push({type: "V", values: [y]});
currentY = y;
}
else if (type === "S") {
var x2 = seg.values[0];
var y2 = seg.values[1];
var x = seg.values[2];
var y = seg.values[3];
absolutizedPathData.push({type: "S", values: [x2, y2, x, y]});
currentX = x;
currentY = y;
}
else if (type === "s") {
var x2 = currentX + seg.values[0];
var y2 = currentY + seg.values[1];
var x = currentX + seg.values[2];
var y = currentY + seg.values[3];
absolutizedPathData.push({type: "S", values: [x2, y2, x, y]});
currentX = x;
currentY = y;
}
else if (type === "T") {
var x = seg.values[0];
var y = seg.values[1]
absolutizedPathData.push({type: "T", values: [x, y]});
currentX = x;
currentY = y;
}
else if (type === "t") {
var x = currentX + seg.values[0];
var y = currentY + seg.values[1]
absolutizedPathData.push({type: "T", values: [x, y]});
currentX = x;
currentY = y;
}
else if (type === "Z" || type === "z") {
absolutizedPathData.push({type: "Z", values: []});
currentX = subpathX;
currentY = subpathY;
}
});
return absolutizedPathData;
};
// @info
// Takes path data that consists only from absolute commands, returns path data that consists only from
// "M", "L", "C" and "Z" commands.
var reducePathData = function(pathData) {
var reducedPathData = [];
var lastType = null;
var lastControlX = null;
var lastControlY = null;
var currentX = null;
var currentY = null;
var subpathX = null;
var subpathY = null;
pathData.forEach( function(seg) {
if (seg.type === "M") {
var x = seg.values[0];
var y = seg.values[1];
reducedPathData.push({type: "M", values: [x, y]});
subpathX = x;
subpathY = y;
currentX = x;
currentY = y;
}
else if (seg.type === "C") {
var x1 = seg.values[0];
var y1 = seg.values[1];
var x2 = seg.values[2];
var y2 = seg.values[3];
var x = seg.values[4];
var y = seg.values[5];
reducedPathData.push({type: "C", values: [x1, y1, x2, y2, x, y]});
lastControlX = x2;
lastControlY = y2;
currentX = x;
currentY = y;
}
else if (seg.type === "L") {
var x = seg.values[0];
var y = seg.values[1];
reducedPathData.push({type: "L", values: [x, y]});
currentX = x;
currentY = y;
}
else if (seg.type === "H") {
var x = seg.values[0];
reducedPathData.push({type: "L", values: [x, currentY]});
currentX = x;
}
else if (seg.type === "V") {
var y = seg.values[0];
reducedPathData.push({type: "L", values: [currentX, y]});
currentY = y;
}
else if (seg.type === "S") {
var x2 = seg.values[0];
var y2 = seg.values[1];
var x = seg.values[2];
var y = seg.values[3];
var cx1, cy1;
if (lastType === "C" || lastType === "S") {
cx1 = currentX + (currentX - lastControlX);
cy1 = currentY + (currentY - lastControlY);
}
else {
cx1 = currentX;
cy1 = currentY;
}
reducedPathData.push({type: "C", values: [cx1, cy1, x2, y2, x, y]});
lastControlX = x2;
lastControlY = y2;
currentX = x;
currentY = y;
}
else if (seg.type === "T") {
var x = seg.values[0];
var y = seg.values[1];
var x1, y1;
if (lastType === "Q" || lastType === "T") {
x1 = currentX + (currentX - lastControlX);
y1 = currentY + (currentY - lastControlY);
}
else {
x1 = currentX;
y1 = currentY;
}
var cx1 = currentX + 2 * (x1 - currentX) / 3;
var cy1 = currentY + 2 * (y1 - currentY) / 3;
var cx2 = x + 2 * (x1 - x) / 3;
var cy2 = y + 2 * (y1 - y) / 3;
reducedPathData.push({type: "C", values: [cx1, cy1, cx2, cy2, x, y]});
lastControlX = x1;
lastControlY = y1;
currentX = x;
currentY = y;
}
else if (seg.type === "Q") {
var x1 = seg.values[0];
var y1 = seg.values[1];
var x = seg.values[2];
var y = seg.values[3];
var cx1 = currentX + 2 * (x1 - currentX) / 3;
var cy1 = currentY + 2 * (y1 - currentY) / 3;
var cx2 = x + 2 * (x1 - x) / 3;
var cy2 = y + 2 * (y1 - y) / 3;
reducedPathData.push({type: "C", values: [cx1, cy1, cx2, cy2, x, y]});
lastControlX = x1;
lastControlY = y1;
currentX = x;
currentY = y;
}
else if (seg.type === "A") {
var r1 = Math.abs(seg.values[0]);
var r2 = Math.abs(seg.values[1]);
var angle = seg.values[2];
var largeArcFlag = seg.values[3];
var sweepFlag = seg.values[4];
var x = seg.values[5];
var y = seg.values[6];
if (r1 === 0 || r2 === 0) {
reducedPathData.push({type: "C", values: [currentX, currentY, x, y, x, y]});
currentX = x;
currentY = y;
}
else {
if (currentX !== x || currentY !== y) {
var curves = arcToCubicCurves(currentX, currentY, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
curves.forEach( function(curve) {
reducedPathData.push({type: "C", values: curve});
});
currentX = x;
currentY = y;
}
}
}
else if (seg.type === "Z") {
reducedPathData.push(seg);
currentX = subpathX;
currentY = subpathY;
}
lastType = seg.type;
});
return reducedPathData;
};
SVGPathElement.prototype.setAttribute = function(name, value) {
if (name === "d") {
this[$cachedPathData] = null;
this[$cachedNormalizedPathData] = null;
}
setAttribute.call(this, name, value);
};
SVGPathElement.prototype.removeAttribute = function(name, value) {
if (name === "d") {
this[$cachedPathData] = null;
this[$cachedNormalizedPathData] = null;
}
removeAttribute.call(this, name);
};
SVGPathElement.prototype.getPathData = function(options) {
if (options && options.normalize) {
if (this[$cachedNormalizedPathData]) {
return clonePathData(this[$cachedNormalizedPathData]);
}
else {
var pathData;
if (this[$cachedPathData]) {
pathData = clonePathData(this[$cachedPathData]);
}
else {
pathData = parsePathDataString(this.getAttribute("d") || "");
this[$cachedPathData] = clonePathData(pathData);
}
var normalizedPathData = reducePathData(absolutizePathData(pathData));
this[$cachedNormalizedPathData] = clonePathData(normalizedPathData);
return normalizedPathData;
}
}
else {
if (this[$cachedPathData]) {
return clonePathData(this[$cachedPathData]);
}
else {
var pathData = parsePathDataString(this.getAttribute("d") || "");
this[$cachedPathData] = clonePathData(pathData);
return pathData;
}
}
};
SVGPathElement.prototype.setPathData = function(pathData) {
if (pathData.length === 0) {
if (isIE) {
// @bugfix https://github.com/mbostock/d3/issues/1737
this.setAttribute("d", "");
}
else {
this.removeAttribute("d");
}
}
else {
var d = "";
for (var i = 0, l = pathData.length; i < l; i += 1) {
var seg = pathData[i];
if (i > 0) {
d += " ";
}
d += seg.type;
if (seg.values && seg.values.length > 0) {
d += " " + seg.values.join(" ");
}
}
this.setAttribute("d", d);
}
};
SVGRectElement.prototype.getPathData = function(options) {
var x = this.x.baseVal.value;
var y = this.y.baseVal.value;
var width = this.width.baseVal.value;
var height = this.height.baseVal.value;
var rx = this.hasAttribute("rx") ? this.rx.baseVal.value : this.ry.baseVal.value;
var ry = this.hasAttribute("ry") ? this.ry.baseVal.value : this.rx.baseVal.value;
if (rx > width / 2) {
rx = width / 2;
}
if (ry > height / 2) {
ry = height / 2;
}
var pathData = [
{type: "M", values: [x+rx, y]},
{type: "H", values: [x+width-rx]},
{type: "A", values: [rx, ry, 0, 0, 1, x+width, y+ry]},
{type: "V", values: [y+height-ry]},
{type: "A", values: [rx, ry, 0, 0, 1, x+width-rx, y+height]},
{type: "H", values: [x+rx]},
{type: "A", values: [rx, ry, 0, 0, 1, x, y+height-ry]},
{type: "V", values: [y+ry]},
{type: "A", values: [rx, ry, 0, 0, 1, x+rx, y]},
{type: "Z", values: []}
];
// Get rid of redundant "A" segs when either rx or ry is 0
pathData = pathData.filter(function(s) {
return s.type === "A" && (s.values[0] === 0 || s.values[1] === 0) ? false : true;
});
if (options && options.normalize === true) {
pathData = reducePathData(pathData);
}
return pathData;
};
SVGCircleElement.prototype.getPathData = function(options) {
var cx = this.cx.baseVal.value;
var cy = this.cy.baseVal.value;
var r = this.r.baseVal.value;
var pathData = [
{ type: "M", values: [cx + r, cy] },
{ type: "A", values: [r, r, 0, 0, 1, cx, cy+r] },
{ type: "A", values: [r, r, 0, 0, 1, cx-r, cy] },
{ type: "A", values: [r, r, 0, 0, 1, cx, cy-r] },
{ type: "A", values: [r, r, 0, 0, 1, cx+r, cy] },
{ type: "Z", values: [] }
];
if (options && options.normalize === true) {
pathData = reducePathData(pathData);
}
return pathData;
};
SVGEllipseElement.prototype.getPathData = function(options) {
var cx = this.cx.baseVal.value;
var cy = this.cy.baseVal.value;
var rx = this.rx.baseVal.value;
var ry = this.ry.baseVal.value;
var pathData = [
{ type: "M", values: [cx + rx, cy] },
{ type: "A", values: [rx, ry, 0, 0, 1, cx, cy+ry] },
{ type: "A", values: [rx, ry, 0, 0, 1, cx-rx, cy] },
{ type: "A", values: [rx, ry, 0, 0, 1, cx, cy-ry] },
{ type: "A", values: [rx, ry, 0, 0, 1, cx+rx, cy] },
{ type: "Z", values: [] }
];
if (options && options.normalize === true) {
pathData = reducePathData(pathData);
}
return pathData;
};
SVGLineElement.prototype.getPathData = function() {
return [
{ type: "M", values: [this.x1.baseVal.value, this.y1.baseVal.value] },
{ type: "L", values: [this.x2.baseVal.value, this.y2.baseVal.value] }
];
};
SVGPolylineElement.prototype.getPathData = function() {
var pathData = [];
for (var i = 0; i < this.points.numberOfItems; i += 1) {
var point = this.points.getItem(i);
pathData.push({
type: (i === 0 ? "M" : "L"),
values: [point.x, point.y]
});
}
return pathData;
};
SVGPolygonElement.prototype.getPathData = function() {
var pathData = [];
for (var i = 0; i < this.points.numberOfItems; i += 1) {
var point = this.points.getItem(i);
pathData.push({
type: (i === 0 ? "M" : "L"),
values: [point.x, point.y]
});
}
pathData.push({
type: "Z",
values: []
});
return pathData;
};
})();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment