Advertisement
Guest User

Untitled

a guest
Nov 18th, 2019
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.52 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset=utf-8>
  5. <title>yes</title>
  6. <style>
  7. body{background-color:lightgrey;font-family:monospace;}
  8. </style>
  9. </head>
  10. <body>
  11. <h1>fractal</h1>
  12. <canvas oncontextmenu="event.preventDefault()" style="border: 1px solid black" width=500 height=500 id=canvas></canvas>
  13. <br>
  14. <p id=output>Left click to zoom in, right click to zoom out, middle click to recentre.</p>
  15. <p>Fractal Type: <select id="typesel"></select></p>
  16. <p>Max Iterations: <span id="iterations_disp">250</span><input type="range" id="iterations" min="100" max="1000" step="10" value="250"></p>
  17. <script>
  18. // GLOBAL STATE
  19. var PRM = {};
  20.  
  21. var canvas = document.getElementById("canvas");
  22. var ctx = canvas.getContext("2d");
  23. var imageData = ctx.createImageData(500,500);
  24.  
  25.  
  26. // FRACTAL TYPES
  27. PRM.fractype = "mandelbrot";
  28.  
  29. function N(re,im) { return new Complex(re,im) }
  30. var fractalTypes = {
  31. mandelbrot : ["Mandelbrot", function(z,c) { return z.squared().add(c) }],
  32. ship : ["Burning Ship", function(z,c) { return N(Math.abs(z.re), Math.abs(z.im)).squared().add(c) }],
  33. tricorn : ["Tricorn / Mandelbar", function(z,c) { return N(z.re, -z.im).squared().add(c) }],
  34. }
  35.  
  36. Object.getOwnPropertyNames(fractalTypes).forEach(function(type) {
  37. var opt = document.createElement("option");
  38. opt.value = type;
  39. opt.text = fractalTypes[type][0];
  40. document.getElementById("typesel").add(opt);
  41. });
  42.  
  43.  
  44. // HSL TO RGB
  45. // "borrowed" from stackoverflow
  46. function hslToRgb(h, s, l){
  47. var r, g, b;
  48.  
  49. if(s == 0){
  50. r = g = b = l; // achromatic
  51. }else{
  52. var hue2rgb = function hue2rgb(p, q, t){
  53. if(t < 0) t += 1;
  54. if(t > 1) t -= 1;
  55. if(t < 1/6) return p + (q - p) * 6 * t;
  56. if(t < 1/2) return q;
  57. if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
  58. return p;
  59. }
  60.  
  61. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  62. var p = 2 * l - q;
  63. r = hue2rgb(p, q, h + 1/3);
  64. g = hue2rgb(p, q, h);
  65. b = hue2rgb(p, q, h - 1/3);
  66. }
  67.  
  68. return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
  69. }
  70.  
  71. // COMPLEX NUMBER ARITHMETIC
  72. function Complex(re, im) {
  73. this.re = re;
  74. this.im = im;
  75. }
  76. Complex.prototype.squared = function() {
  77. // (a+ib)(a+ib) = a^2 - b^2 + 2abi
  78. return new Complex( (this.re ** 2) - (this.im ** 2), 2 * this.re * this.im);
  79. }
  80. Complex.prototype.add = function(other) {
  81. return new Complex( this.re + other.re, this.im + other.im );
  82. }
  83. Complex.prototype.copy = function() {
  84. return new Complex(this.re, this.im);
  85. }
  86. Complex.prototype.isEscaped = function() {
  87. return (this.re ** 2) + (this.im ** 2) >=4;
  88. }
  89. Complex.prototype.toString = function() {
  90. return this.re + " + " + this.im + "i";
  91. }
  92.  
  93. var DEF = {
  94. zoom: 170,
  95. offset: new Complex(-.7,0)
  96. };
  97.  
  98. // POSITION CONVERTING
  99. PRM.zoom = DEF.zoom;
  100. PRM.offset = DEF.offset;
  101. function getFromPos(x,y) {
  102. return new Complex(((x-250)/PRM.zoom), (y-250)/PRM.zoom).add(PRM.offset);
  103. }
  104.  
  105. // INTERACTION
  106. document.getElementById("typesel").addEventListener("change", function(e) {
  107. PRM.zoom = DEF.zoom;
  108. PRM.offset = DEF.offset;
  109. PRM.fractype = this.value;
  110. go();
  111. });
  112.  
  113. canvas.addEventListener("mousedown", function(e) {
  114. e.preventDefault();
  115. var x = e.pageX - canvas.offsetLeft;
  116. var y = e.pageY - canvas.offsetTop;
  117. var c = getFromPos(x,y);
  118. document.getElementById("output").innerHTML = c.toString() + "; " + PRM.zoom / 500 + "x";
  119. PRM.offset = c;
  120. if (e.button == 0) {
  121. PRM.zoom *= 1.5;
  122. } else if (e.button == 2) {
  123. PRM.zoom /= 1.5;
  124. }
  125. go();
  126. });
  127. PRM.maxIter = 250;
  128. document.getElementById("iterations").addEventListener("change", function(e) {
  129. var val = this.value;
  130. PRM.maxIter = val;
  131. document.getElementById("iterations_disp").innerHTML = val.toString();
  132. go();
  133. });
  134. // MAIN
  135. function go() {
  136. iterFn = fractalTypes[PRM.fractype][1];
  137. for (var x = 0; x < 500; x++) {
  138. for (var y = 0; y < 500; y++) {
  139. var p = 500*y + x;
  140. var idx = 4 * p;
  141. var c = getFromPos(x,y);
  142. var z = c;
  143. var i;
  144. var escaped = false;
  145. for (i = 0; i < PRM.maxIter; i++) {
  146.  
  147. z = iterFn(z,c);
  148. if (z.isEscaped()) {
  149. escaped = true;
  150. break;
  151. }
  152. }
  153. if (escaped) {
  154. var rgb = hslToRgb( ((i)/100) %1, 1, .5 );
  155. g = rgb[1]
  156. r = rgb[0]
  157. b = rgb[2]
  158. } else {
  159. r = g = b = 0;
  160. }
  161. imageData.data[idx + 0] = r;
  162. imageData.data[idx + 1] = g;
  163. imageData.data[idx + 2] = b;
  164. imageData.data[idx + 3] = 255;
  165. }
  166. }
  167. ctx.putImageData(imageData, 0, 0);
  168. }
  169.  
  170. go();
  171.  
  172. </script>
  173. </body>
  174. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement