@polytrope/

julia-fractals-julia-set

HTML, CSS, JS

No description

fork
loading
Files
  • index.html
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<!DOCTYPE html>
<html>
<head>
  <title>Julia Fractals</title>
</head>

<style>
  body {
    background: black;
    color: white;
  }
  canvas {
    border: 1px solid white;
  }
</style>

<body>
  <h2></h2>
  <canvas></canvas>
</body>

<!-- Import math.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.6.0/math.min.js"></script>

<script>

// The HTML elements we are using
var header = document.querySelector('h2')
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')

// The size of our canvas
var width = 200
var height = 200

// Set the size of our canvas
canvas.width = width
canvas.height = height

// The XY coordinates of the mouse over the canvas
var mouseX = 0
var mouseY = 0

// The point we use for C in our Julia Set equation
var constant = math.complex(0.28, 0.01)

// The maximum number of times we iterate a point to see if it escapes
var maxIterations = 64

// Apply the Julia Set formula to see if point z "escapes"
function julia(z, i = 0) {
  // Apply the Julia Set formula: z*z+constant
  z = z.mul(z)
  z = z.add(constant)

  // Has our point escaped, or hit the iteration limit?
  if (math.abs(z) > 2 || i == maxIterations)
    // If so, return number of iterations
    return i
  else
    // If not, iterate again!
    return julia(z, i+1)
}

// Turn a point on the complex plane into a color
function pointToColor(point) {
  // How many iterations on this point before it escapes?
  var iterations = julia(point)

  // What percentage of our limit is that?
  var percentage = iterations/maxIterations

  var red = percentage*255
  var green = percentage*255
  var blue = percentage*255

  // Create a color from that percentage
  return `rgb(${red}, ${green}, ${blue})`
}

// Turn XY pixel coordinates into a point on the complex plane
function pixelToPoint(x, y) {
  // Map percentage of total width/height to a value from -1 to +1
  var zx = (x/width)*2-1
  var zy = 1-(y/height)*2

  // Create a complex number based on our new XY values
  return math.complex(zx, zy)
}

// Draw a single pixel on our canvas
function drawPixel(x, y, color) {
  ctx.fillStyle = color
  ctx.fillRect(x, y, 1, 1)
}

// Redraw our canvas
function draw() {
  // Loop over every column of pixels
  for (var y = 0; y < height; y++) {
    // Loop over every row of pixels
    for (var x = 0; x < width; x++) {
      // Turn this pixel into a point in the complex plane
      var point = pixelToPoint(x, y)

      // Turn that point into a color
      var color = pointToColor(point)

      // Draw over this pixel with that color
      drawPixel(x, y, color)
    }
  }
}

// Update the elements that need to change
function update() {
  header.innerHTML = constant.toString()
  draw()
}

// What to do when the mouse moves over the canvas
function move(event) {
  // Get the mouse's XY coordinates on canvas
  mouseX = event.clientX-canvas.offsetLeft
  mouseY = event.clientY-canvas.offsetTop

  // Turn mouse coordinates into a point on the complex plane
  constant = pixelToPoint(mouseX, mouseY)

  // Round that point off to the nearest 0.01
  constant.re = math.round(constant.re*100)/100
  constant.im = math.round(constant.im*100)/100

  // Update everything!
  update()
}

// Trigger move every time the mouse moves over canvas
canvas.addEventListener('pointermove', move)

// Update everything!
update()

</script>
</html>
result
console