{"id":487,"date":"2011-08-28T00:17:50","date_gmt":"2011-08-28T00:17:50","guid":{"rendered":"http:\/\/tech.avant.net\/q\/?p=487"},"modified":"2012-12-25T22:39:24","modified_gmt":"2012-12-25T22:39:24","slug":"html5-canvas-mandelbrot","status":"publish","type":"post","link":"https:\/\/tech.avant.net\/q\/html5-canvas-mandelbrot\/","title":{"rendered":"HTML5 canvas Mandelbrot"},"content":{"rendered":"<p>I would like to create an animated Mandelbrot visualization using JavaScript on an HTML5 &lt;canvas&gt; element. The Mandelbrot set, popularized by Beno\u00eet Mandelbrot, is the set of complex numbers that remain bounded under the function <i>z<\/i><sub><i>n<\/i>+1<\/sub> = <i>z<\/i><sub><i>n<\/i><\/sub><sup>2<\/sup> + <i>c<\/i>. This is known as an escape function; that is, regardless of the size of n, <i>z<\/i><sub><i>n<\/i><\/sub> never &#8220;escapes&#8221;. Computing the Mandelbrot set can be as computationally complex as desired for a given visualization.<\/p>\n<p>In JavaScript, the escape function can be written as follows:<\/p>\n<pre class=\"sh_javascript\">\r\nMandelbrot.prototype.escapeFunc = function(x, y) {\r\n  r = 0.0; i = 0.0; m = 0.0;\r\n  j = 0;\r\n  while ((j < this.max) &#038;&#038; (m < 4.0)) {\r\n    j++;\r\n    m = r * r - i * i;\r\n    i = 2.0 * r * i + y;\r\n    r = m + x;\r\n  }\r\n  return j;\r\n}\r\n<\/pre>\n<p>For a given HTML5 canvas element, such as<\/p>\n<pre class=\"sh_html\">\r\n&lt;canvas id=\"mandelbrot\" width=\"512\" height=\"512\"&gt;\r\n<\/pre>\n<p>A Manelbrot set over the complex plane can be represented with the follow object<\/p>\n<pre class=\"sh_javascript\">\r\nfunction Mandelbrot(m) {\r\n  this.m = m;\r\n  this.c = m.getContext(\"2d\");\r\n  this.width = m.width;\r\n  this.height = m.height;\r\n  this.SX = -1.75; \/\/ start value real\r\n  this.EX = 0.6;    \/\/ end value real\r\n  this.SY = -1.125; \/\/ start value imaginary\r\n  this.EY = 1.125;  \/\/ end value imaginary\r\n  this.xzoom = (this.EX - this.SX) \/ (this.width*1.0);\r\n  this.yzoom = (this.EY - this.SY) \/ (this.height*1.0);\r\n}\r\n<\/pre>\n<p>Given these functions, rendering a Mandelbrot set on an HTML5 canvas element is as simple as looping through each of the pixels of the canvas, calculating the escape value, and drawing the pixel.  Here is a simple render function:<\/p>\n<pre class=\"sh_javascript\">\r\nMandelbrot.prototype.render = function() {\r\n  var prev_h = 0;\r\n  for (var x = 0; x < this.width; x=x+1) {\r\n    for (var y = 0; y < this.height; y=y+1) {\r\n      esc = this.escapeFunc(this.SX + x*this.xzoom, this.SY + y*this.yzoom);\r\n      h = 360 * (esc\/this.max)\r\n      if (h != prev_h) {\r\n         perc = Math.floor(100*(h\/360))\r\n         this.c.fillStyle='hsla('+ h + ','+ (perc+100) +'%,'+ (60-perc) +'%,'+ this.opacity  +')';\r\n         prev_h = h;\r\n      }\r\n      this.c.fillRect(x,y,1,1);\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>If you have an HTML5 compatible browser you should see an animated example below:<\/p>\n<p><canvas id=\"mandelbrot\" width=\"512\" height=\"512\" style=\"border: 1px solid black;\">your browser does not support the HTML5 canvas element<\/canvas><\/p>\n<div id=\"dbg\"><\/div>\n<p><script type=\"text\/javascript\" src=\"\/sandbox\/mandelbrot_animate.js\"><\/script><br \/>\n<script type=\"text\/javascript\">\n<!--\n  var mandelbrot = document.getElementById(\"mandelbrot\");\n  var fractal = new Mandelbrot(mandelbrot);\n  start_d = new Date(); start_t = start_d.getTime();\n  fractal.state = 'start_render';\n  fractal.running = true;\n  rendering = setInterval(function() {\n    fractal.render_t();\n  }, 60);\n\/\/--><\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I would like to create an animated Mandelbrot visualization using JavaScript on an HTML5 &lt;canvas&gt; element. The Mandelbrot set, popularized by Beno\u00eet Mandelbrot, is the set of complex numbers that remain bounded under the function zn+1 = zn2 + c. This is known as an escape function; that is, regardless of the size of n, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11,9],"tags":[],"_links":{"self":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts\/487"}],"collection":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/comments?post=487"}],"version-history":[{"count":10,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts\/487\/revisions"}],"predecessor-version":[{"id":712,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/posts\/487\/revisions\/712"}],"wp:attachment":[{"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/media?parent=487"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/categories?post=487"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tech.avant.net\/q\/wp-json\/wp\/v2\/tags?post=487"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}