Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset=utf-8>
- <title>yes</title>
- <style>
- body{background-color:lightgrey;font-family:monospace;}
- </style>
- </head>
- <body>
- <h1>fractal</h1>
- <canvas oncontextmenu="event.preventDefault()" style="border: 1px solid black" width=500 height=500 id=canvas></canvas>
- <br>
- <p id=output>Left click to zoom in, right click to zoom out, middle click to recentre.</p>
- <p>Fractal Type: <select id="typesel"></select></p>
- <p>Max Iterations: <span id="iterations_disp">250</span><input type="range" id="iterations" min="100" max="1000" step="10" value="250"></p>
- <script>
- // GLOBAL STATE
- var PRM = {};
- var canvas = document.getElementById("canvas");
- var ctx = canvas.getContext("2d");
- var imageData = ctx.createImageData(500,500);
- // FRACTAL TYPES
- PRM.fractype = "mandelbrot";
- function N(re,im) { return new Complex(re,im) }
- var fractalTypes = {
- mandelbrot : ["Mandelbrot", function(z,c) { return z.squared().add(c) }],
- ship : ["Burning Ship", function(z,c) { return N(Math.abs(z.re), Math.abs(z.im)).squared().add(c) }],
- tricorn : ["Tricorn / Mandelbar", function(z,c) { return N(z.re, -z.im).squared().add(c) }],
- }
- Object.getOwnPropertyNames(fractalTypes).forEach(function(type) {
- var opt = document.createElement("option");
- opt.value = type;
- opt.text = fractalTypes[type][0];
- document.getElementById("typesel").add(opt);
- });
- // HSL TO RGB
- // "borrowed" from stackoverflow
- function hslToRgb(h, s, l){
- var r, g, b;
- if(s == 0){
- r = g = b = l; // achromatic
- }else{
- var hue2rgb = function hue2rgb(p, q, t){
- if(t < 0) t += 1;
- if(t > 1) t -= 1;
- if(t < 1/6) return p + (q - p) * 6 * t;
- if(t < 1/2) return q;
- if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
- return p;
- }
- var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
- var p = 2 * l - q;
- r = hue2rgb(p, q, h + 1/3);
- g = hue2rgb(p, q, h);
- b = hue2rgb(p, q, h - 1/3);
- }
- return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
- }
- // COMPLEX NUMBER ARITHMETIC
- function Complex(re, im) {
- this.re = re;
- this.im = im;
- }
- Complex.prototype.squared = function() {
- // (a+ib)(a+ib) = a^2 - b^2 + 2abi
- return new Complex( (this.re ** 2) - (this.im ** 2), 2 * this.re * this.im);
- }
- Complex.prototype.add = function(other) {
- return new Complex( this.re + other.re, this.im + other.im );
- }
- Complex.prototype.copy = function() {
- return new Complex(this.re, this.im);
- }
- Complex.prototype.isEscaped = function() {
- return (this.re ** 2) + (this.im ** 2) >=4;
- }
- Complex.prototype.toString = function() {
- return this.re + " + " + this.im + "i";
- }
- var DEF = {
- zoom: 170,
- offset: new Complex(-.7,0)
- };
- // POSITION CONVERTING
- PRM.zoom = DEF.zoom;
- PRM.offset = DEF.offset;
- function getFromPos(x,y) {
- return new Complex(((x-250)/PRM.zoom), (y-250)/PRM.zoom).add(PRM.offset);
- }
- // INTERACTION
- document.getElementById("typesel").addEventListener("change", function(e) {
- PRM.zoom = DEF.zoom;
- PRM.offset = DEF.offset;
- PRM.fractype = this.value;
- go();
- });
- canvas.addEventListener("mousedown", function(e) {
- e.preventDefault();
- var x = e.pageX - canvas.offsetLeft;
- var y = e.pageY - canvas.offsetTop;
- var c = getFromPos(x,y);
- document.getElementById("output").innerHTML = c.toString() + "; " + PRM.zoom / 500 + "x";
- PRM.offset = c;
- if (e.button == 0) {
- PRM.zoom *= 1.5;
- } else if (e.button == 2) {
- PRM.zoom /= 1.5;
- }
- go();
- });
- PRM.maxIter = 250;
- document.getElementById("iterations").addEventListener("change", function(e) {
- var val = this.value;
- PRM.maxIter = val;
- document.getElementById("iterations_disp").innerHTML = val.toString();
- go();
- });
- // MAIN
- function go() {
- iterFn = fractalTypes[PRM.fractype][1];
- for (var x = 0; x < 500; x++) {
- for (var y = 0; y < 500; y++) {
- var p = 500*y + x;
- var idx = 4 * p;
- var c = getFromPos(x,y);
- var z = c;
- var i;
- var escaped = false;
- for (i = 0; i < PRM.maxIter; i++) {
- z = iterFn(z,c);
- if (z.isEscaped()) {
- escaped = true;
- break;
- }
- }
- if (escaped) {
- var rgb = hslToRgb( ((i)/100) %1, 1, .5 );
- g = rgb[1]
- r = rgb[0]
- b = rgb[2]
- } else {
- r = g = b = 0;
- }
- imageData.data[idx + 0] = r;
- imageData.data[idx + 1] = g;
- imageData.data[idx + 2] = b;
- imageData.data[idx + 3] = 255;
- }
- }
- ctx.putImageData(imageData, 0, 0);
- }
- go();
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement