-
Notifications
You must be signed in to change notification settings - Fork 0
/
julia.html
116 lines (104 loc) · 3.56 KB
/
julia.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
<html>
<head>
<script type="text/javascript">
var windowSize = {minX: -1.4, maxX: 1.4, minY: -1.1, maxY: 1.1};
var maxIter = 100;
var defaultMagn = 2;
var [c_r, c_i] = [(1+Math.sqrt(5))/2-2,(1+Math.sqrt(5))/2-1];
var R = 8;
var canvas;
var ctx;
function loadGlobalVariables() {
params = window.location.hash.split('#')
windowSize.minX = parseFloat(params[1]);
windowSize.maxX = parseFloat(params[2]);
windowSize.minY = parseFloat(params[3]);
windowSize.maxY = parseFloat(params[4]);
maxIter = parseInt(params[5]);
defaultMagn = parseFloat(params[6]);
canvas.height = parseInt(params[7]);
canvas.width = parseInt(params[8]);
c_r = parseFloat(params[9]);
c_i = parseFloat(params[10]);
R = parseFloat(params[11]);
}
function setGlobalVariables() {
window.location.hash = "#" + windowSize.minX + "#" +
windowSize.maxX + "#" +
windowSize.minY + "#" +
windowSize.maxY + "#" +
maxIter + "#" +
defaultMagn + "#" +
canvas.height + "#" +
canvas.width + "#" +
c_r + "#" +
c_i + "#" +
R;
}
function base(n,b) {
let o = '';
let A = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if(b<2 || b>A.length) throw new Error('Invalid base');
let e=0;
while(n>0) {
d = n%b;
o = A.charAt(d) + o;
n -= d;
n /= b;
e += 1;
}
return o;
}
function drawJuliaSet() {
let coordX, coordY, real, imag, iter;
for(let j=0; j<canvas.width; j++) {
for(let i=0; i<canvas.width; i++) {
coordX = windowSize.minX + (i/canvas.width)*(windowSize.maxX - windowSize.minX);
coordY = windowSize.maxY - (j/canvas.height)*(windowSize.maxY - windowSize.minY);
real = (x,y) => x*x-y*y+c_r;
imag = (x,y) => 2*x*y+c_i;
in_set = (x,y,R) => Math.pow(real(x,y),2) + Math.pow(imag(x,y),2) <= R*R*(R*R-2*R+1); // |c| <= R^2 - R
iter = 0;
[iterX, iterY] = [coordX, coordY];
while(in_set(iterX, iterY, R) && iter < maxIter) {
[iterX, iterY] = [real(iterX,iterY), imag(iterX,iterY)];
iter++;
}
colorPick = (iter) => "#" + "00" + base(Math.floor((Math.pow(256,1)-1)*iter/maxIter), 16) + "00";
ctx.fillStyle = iter==maxIter ? "#000000" : colorPick(iter);
ctx.fillRect(i,j,1,1);
}
}
}
function zoom(x, y, magn) {
let coordX = windowSize.minX + (x/canvas.width)*(windowSize.maxX - windowSize.minX);
let coordY = windowSize.maxY - (y/canvas.height)*(windowSize.maxY - windowSize.minY);
let sizeX = (windowSize.maxX - windowSize.minX) / magn;
let sizeY = (windowSize.maxY - windowSize.minY) / magn;
windowSize = {minX: coordX - sizeX / 2,
maxX: coordX + sizeX / 2,
minY: coordY - sizeY / 2,
maxY: coordY + sizeY / 2};
setGlobalVariables();
drawJuliaSet();
}
window.onload = function() {
canvas = document.querySelector("#canvas");
ctx = canvas.getContext("2d");
if(window.location.hash) {
loadGlobalVariables();
} else {
setGlobalVariables();
};
drawJuliaSet();
canvas.addEventListener("click", function(e) { console.log(e); if(e.button===0) zoom(e.offsetX, e.offsetY, defaultMagn); });
window.addEventListener("hashchange", function(e) { console.log(e); window.location.hash = e.target.location.hash; loadGlobalVariables(); drawJuliaSet();});
window.addEventListener("contextmenu", function(e) { zoom(e.offsetX, e.offsetY, 1/defaultMagn); e?.cancelable && e.preventDefault() } );
}
</script>
</head>
<body style="background-color: black;">
<canvas id="canvas" height=501 width=501></canvas><br>
<button onclick="window.location = window.location.origin + window.location.pathname">Reset</button>
</body>
</html>