JavaScript で SVG の角を丸める方法のメモ

二次スプライン曲線を利用して少ない手間で角を曲げる方法。
Firefox 3.0.5, Safari 3.2.1, Opera 9.63 にて動作確認済み。

ソース (roundEdge.xml)

<?xml version='1.0'?>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:svg="http://www.w3.org/2000/svg">

<head>
	<title>JavaScript で SVG の角を丸める</title>
	<script type="text/javascript">
		<![CDATA[
		
		function roundEdge(path, radius) {
			
			//パスをリセット
			resetPath();
		
			//各ポイントの取得
			var A = path.pathSegList.getItem(0); //左の点
			var B = path.pathSegList.getItem(1); //真ん中の点
			var C = path.pathSegList.getItem(2); //右の点
			
			//任意の2点から角度を割り出す
			var angle1 = Math.atan2(B.y - A.y, B.x - A.x); //A,B間の角度
			var angle2 = Math.atan2(C.y - B.y, C.x - B.x); //B,C間の角度
		
			//二次スプライン曲線用のポイントB1とB2を割り出す
			var B1x = B.x - (Math.cos(angle1) * radius);
			var B1y = B.y - (Math.sin(angle1) * radius);
		
			var B2x = B.x + (Math.cos(angle2) * radius);
			var B2y = B.y + (Math.sin(angle2) * radius);
		
			//二次スプライン曲線を利用して角を丸める
			path.setAttribute('d', 'M '+A.x+','+A.y+' L '+B1x+','+B1y+' Q '+B.x+','+B.y+' '+B2x+','+B2y+' L '+C.x+','+C.y);
				
		}
		
		function resetPath() {
			document.getElementById('path').setAttribute('d', 'M 73.574464,78.567376 L 172.96453,26.936173 L 509.85816,121.16312');
			return false;
		}
	
		function round() {
			
			var path = document.getElementById('path');
			var radius = Number(document.getElementById('radius').value);
			
			if(radius <= 0 || isNaN(radius)) {
				window.alert('正数を入力してください。');
				return false;
			}
			
			roundEdge(path, radius);
			return false;
		}
	
		]]>
	</script>	
</head>

<body>
  <h1>JavaScript で SVG の角を丸める</h1>
  <form action="./" onreset="return resetPath();" onsubmit="return round();">
  	<input type="text" id="radius" value="20" />
  	<input type="submit" name="submit" value="角を丸める" />
  	<input type="reset" value="リセット" />
  </form>
  <p>
    <svg:svg width="600" height="300">
     <svg:path
       d="M 73.574464,78.567376 L 172.96453,26.936173 L 509.85816,121.16312"
       id="path"
       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
    </svg:svg>
  </p>

</body>
</html>