156 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| require_once __DIR__ . '/_index.php';
 | |
| 
 | |
| function random_float()
 | |
| {
 | |
|     return mt_rand() / mt_getrandmax();
 | |
| }
 | |
| 
 | |
| function choose_random(array $a)
 | |
| {
 | |
|     return $a[mt_rand() % count($a)];
 | |
| }
 | |
| 
 | |
| 
 | |
| function new_edges()
 | |
| {
 | |
|     return [];
 | |
| }
 | |
| 
 | |
| function has_edge(array $edges, array $edge)
 | |
| {
 | |
|     foreach ($edges as $e) {
 | |
|         if ($e[0] === $edge[0] && $e[1] === $edge[1])
 | |
|             return true;
 | |
|         if ($e[1] === $edge[0] && $e[0] === $edge[1])
 | |
|             return true;
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| function add_edge(array &$edges, array $edge)
 | |
| {
 | |
|     if (has_edge($edges, $edge))
 | |
|         return;
 | |
| 
 | |
|     array_push($edges, $edge);
 | |
| }
 | |
| 
 | |
| 
 | |
| function stars_distance(array $a, array $b)
 | |
| {
 | |
|     return sqrt(pow($a[0] - $b[0], 2) + pow($a[1] - $b[1], 2)) / sqrt(2);
 | |
| }
 | |
| 
 | |
| function stars_random(int $amount = 50)
 | |
| {
 | |
|     $indices = range(0, $amount - 1);
 | |
| 
 | |
|     $points = array_map(function () {
 | |
|         return [
 | |
|             round(max(0.02, min(0.98, random_float())), 3),
 | |
|             round(max(0.02, min(0.98, random_float())), 3),
 | |
|         ];
 | |
|     }, $indices);
 | |
| 
 | |
|     $sizes = array_map(function () {
 | |
|         return round(0.5 + random_float() * 1.2, 3);
 | |
|     }, $indices);
 | |
| 
 | |
|     $edges = new_edges();
 | |
| 
 | |
|     foreach ($indices as $i) {
 | |
|         $choosable = $indices;
 | |
|         usort($choosable, function ($a, $b) use ($points, $i) {
 | |
|             $cmp = stars_distance($points[$i], $points[$a]) - stars_distance($points[$i], $points[$b]);
 | |
|             if ($cmp < 0)
 | |
|                 return -1;
 | |
|             if ($cmp > 0)
 | |
|                 return 1;
 | |
|             return 0;
 | |
|         });
 | |
| 
 | |
|         $choosable = array_slice($choosable, 0, 10);
 | |
| 
 | |
|         $max = 2 + mt_rand() % 2;
 | |
|         for ($j = 0; $j < $max; $j++) {
 | |
|             $o = $i;
 | |
| 
 | |
|             $iter = 0;
 | |
|             while ($o === $i || has_edge($edges, [$i, $o])) {
 | |
|                 $o = choose_random($choosable);
 | |
|                 if ($iter++ > 100)
 | |
|                     break;
 | |
|             }
 | |
| 
 | |
|             if ($iter <= 100)
 | |
|                 add_edge($edges, [$i, $o]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return [$points, $edges, $sizes];
 | |
| }
 | |
| 
 | |
| function stars_container(array $points, array $sizes)
 | |
| {
 | |
|     $html = '<div id="stars-container" aria-hidden="true">';
 | |
| 
 | |
|     $count = count($points);
 | |
|     for ($i = 0; $i < $count; $i++) {
 | |
|         $width = 'max(' . $sizes[$i] . 'vw, ' . $sizes[$i] . 'vh)';
 | |
|         $left = ($points[$i][0] * 100) . 'vw';
 | |
|         $top = ($points[$i][1] * 100) . 'vh';
 | |
|         $html .= "<img src=\"/assets/star.svg\" style=\"position: absolute; width: $width; left: $left; top: $top; translate: -50% -50%;\" />";
 | |
|     }
 | |
| 
 | |
|     $html .= '</div>';
 | |
|     return $html;
 | |
| }
 | |
| 
 | |
| function stars_edges_svg(array $points, array $edges)
 | |
| {
 | |
|     $html = '<svg id="stars-edges" aria-hidden="true">';
 | |
| 
 | |
|     foreach ($edges as [$a, $b]) {
 | |
|         if ($a > $b) {
 | |
|             $tmp = $a;
 | |
|             $a = $b;
 | |
|             $b = $tmp;
 | |
|         }
 | |
| 
 | |
|         [$x1, $y1] = $points[$a];
 | |
|         [$x2, $y2] = $points[$b];
 | |
| 
 | |
|         $x1 *= 100;
 | |
|         $y1 *= 100;
 | |
|         $x2 *= 100;
 | |
|         $y2 *= 100;
 | |
| 
 | |
|         $html .= "<line id=\"$a-$b\" x1=\"$x1%\" y1=\"$y1%\" x2=\"$x2%\" y2=\"$y2%\" stroke=\"white\" stroke-width=\"1.5\" opacity=\"0\" />";
 | |
|     }
 | |
| 
 | |
|     $html .= '</svg>';
 | |
|     return $html;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| function stars_script(array $points, array $edges, array $sizes)
 | |
| {
 | |
|     $js = file_get_contents(__DIR__ . '/js/stars.js');
 | |
| 
 | |
|     return fill_js($js, [
 | |
|         'INDICES' => json_encode(range(0, count($points) - 1)),
 | |
|         'POINTS' => json_encode($points),
 | |
|         'EDGES' => json_encode($edges),
 | |
|         'SIZES' => json_encode($sizes),
 | |
|     ]);
 | |
| }
 | |
| 
 | |
| function stars_styles()
 | |
| {
 | |
|     return file_get_contents(__DIR__ . '/css/stars.css');
 | |
| }
 |