tau-mandala.svg (2928B)
1 <svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 20 20"> 2 <script type="text/javascript"><![CDATA[ 3 'use strict'; 4 5 6 Math.TAU = 2 * Math.PI; 7 8 function internal_angle(n) { 9 return (n - 2) * Math.TAU / (n * 2); 10 }; 11 12 function set_view_box(svg_element, radius, margin) { 13 let high_margin = radius * (1 + margin); 14 let low_margin = -high_margin; 15 let width = high_margin - low_margin; 16 svg.setAttributeNS('http://www.w3.org/2000/svg', 'viewBox', `${low_margin} ${low_margin} ${width} ${width}`); 17 }; 18 19 20 function rotate(point, angle) { 21 let [x, y] = point; 22 let [c_a, s_a] = [Math.cos(angle), Math.sin(angle)]; 23 return [ 24 x * c_a - y * s_a, 25 x * s_a + y * c_a, 26 ]; 27 }; 28 29 30 let radiuses = [1.0]; 31 let polygon_paths = []; 32 for (let nagon = 3; nagon < 100; nagon++) { 33 let radius = radiuses[radiuses.length - 1]; 34 let internal_angle = (nagon - 2) * Math.TAU / (2 * nagon); 35 radius = radius / Math.sin(internal_angle / 2); 36 radiuses.push(radius); 37 let polygon_path = []; 38 for (let i = 0; i < nagon; i++) { 39 let angle = Math.TAU * i / nagon; 40 let point = rotate([0, -radius], angle); 41 polygon_path.push(point); 42 }; 43 polygon_paths.push(polygon_path); 44 }; 45 46 47 let svg = document.getElementsByTagName('svg')[0]; 48 set_view_box(svg, radiuses[radiuses.length - 1], 0.1); 49 radiuses.forEach((r, i, radiuses)=>{ 50 let element = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); 51 element.setAttributeNS(null, 'cx', 0); 52 element.setAttributeNS(null, 'cy', 0); 53 element.setAttributeNS(null, 'r', r); 54 element.setAttributeNS(null, 'fill', 'none'); 55 element.setAttributeNS(null, 'stroke', 'black'); 56 element.setAttributeNS(null, 'stroke-width', 0.1 / (i + 1)); 57 svg.appendChild(element); 58 }); 59 60 polygon_paths.forEach((polygon_path, i, polygon_paths)=>{ 61 let polygon_element = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'); 62 let points = ( 63 polygon_path 64 .map(point=>`${point[0]} ${point[1]}`) 65 .reduce((acc, x)=>acc.concat(' ').concat(x)) 66 ); 67 polygon_element.setAttributeNS(null, 'points', points); 68 polygon_element.setAttributeNS(null, 'fill', 'none'); 69 polygon_element.setAttributeNS(null, 'stroke', 'black'); 70 polygon_element.setAttributeNS(null, 'stroke-width', 0.2 / (i + 1)); 71 let animate_transform_element = document.createElementNS('http://www.w3.org/2000/svg', 'animateTransform'); 72 animate_transform_element.setAttributeNS(null, 'attributeName', 'transform'); 73 animate_transform_element.setAttributeNS(null, 'attributeType', 'XML'); 74 animate_transform_element.setAttributeNS(null, 'type', 'rotate'); 75 animate_transform_element.setAttributeNS(null, 'from', '0 0 0'); 76 animate_transform_element.setAttributeNS(null, 'to', '360 0 0'); 77 animate_transform_element.setAttributeNS(null, 'dur', `${Math.log(i+10, 2)}s`); 78 animate_transform_element.setAttributeNS(null, 'repeatCount', 'indefinite'); 79 polygon_element.appendChild(animate_transform_element); 80 svg.appendChild(polygon_element); 81 }); 82 ]]></script> 83 </svg>