const WIDTH = 800;
const HEIGHT = 600;
const ASPECT_RATIO = WIDTH / HEIGHT;
const ZOOM_SPEED = 1;
let zoom = 0.5;
let zoom_dB = -3;
let posX = -0.75;
let posY = 0;
console.clear();
let canvas = createCanvas(WIDTH, HEIGHT);
canvas.style.border = "2px solid red";
let hueSlider = createLabeledSlider("Barvy", 0, 255, 1, 0);
hueSlider.onInput(redraw);
hueSlider.position(820, 10);
let inputX = createLabeledInputField("X", "number", posX, {
step: 0.001
});
inputX.position(820, 100);
inputX.onChange(function() {
posX = inputX.value();
redraw();
});
let inputY = createLabeledInputField("Y", "number", posY, {
step: 0.001
});
inputY.position(820, 140);
inputY.onChange(function() {
posY = inputY.value();
redraw();
});
let inputZoom = createLabeledInputField("Zoom", "number", zoom, {
step: 0.5,
min: 0.1
});
inputZoom.position(820, 200);
inputZoom.onChange(function() {
zoom = inputZoom.value();
zoom_dB = 10/ZOOM_SPEED*loga(10, zoom);
redraw();
});
let txtX = createParagraph("X: ??");
// txtX.position(820, 100);
let txtY = createParagraph("Y: ??");
// txtY.position(820, 130);
let txtZoom = createParagraph("Zoom: 1:??");
// txtZoom.position(820, 160);
function mandelX(x)
{
return map(x, 0, WIDTH, -1, 1)/zoom;
}
function mandelY(y)
{
return map(y, 0, HEIGHT, -1, 1)/(ASPECT_RATIO*zoom);
}
(function() {
let x0, y0;
let posX0, posY0;
let active = false;
canvas.addEventListener("wheel", e => {
e.preventDefault();
if(sign(e.deltaY) == 1 && zoom <= 0.1)
return;
zoom_dB -= sign(e.deltaY);
zoom = pow(10, zoom_dB*ZOOM_SPEED/10);
inputZoom.value(zoom);
redraw();
});
canvas.addEventListener("mousedown", e => {
x0 = Mouse.canvas.x;
y0 = Mouse.canvas.y;
posX0 = posX;
posY0 = posY;
active = true;
});
canvas.addEventListener("mousemove", e => {
if(!active)
return;
posX = posX0 - (mandelX(Mouse.canvas.x) - mandelX(x0));
posY = posY0 - (mandelY(Mouse.canvas.y) - mandelY(y0));
inputX.value(posX);
inputY.value(posY);
redraw();
});
canvas.addEventListener("mouseup", e => {
posX = posX0 - (mandelX(Mouse.canvas.x) - mandelX(x0));
posY = posY0 - (mandelY(Mouse.canvas.y) - mandelY(y0));
inputX.value(posX);
inputY.value(posY);
redraw();
active = false;
});
})();
function writePixel(img, x, y, r, g, b, a)
{
let data = img.data;
let pos = 4*(x + img.width*y);
data[pos] = r;
data[pos+1] = g;
data[pos+2] = b;
data[pos+3] = a;
}
function wrap(x, min, max)
{
while(x > max)
x -= max;
while(x < min)
x += min;
return x;
}
function mandelbrot(img, xx_ofs, yy_ofs, zoom, MAX_ITERATIONS)
{
// const MAX_ITERATIONS = 100;
const HUE_SPAN = 200+hueSlider.value();
for(let y = 0; y < HEIGHT; ++y) {
const y0 = yy_ofs + mandelY(y);
for(let x = 0; x < WIDTH; ++x) {
const x0 = xx_ofs + mandelX(x);
let re = 0;
let im = 0;
let iteration = 0;
while(re*re + im*im <= 4 && iteration < MAX_ITERATIONS) {
let reTemp = re*re - im*im + x0;
im = 2*re*im + y0;
re = reTemp;
++iteration;
}
if(iteration < MAX_ITERATIONS) {
let it = wrap(iteration+200, 1, MAX_ITERATIONS);
let hue = map(log(it), 0, log(MAX_ITERATIONS), 0, 255);
hue = wrap(hue*10 + HUE_SPAN, 0, 255);
// console.log(hue);
let col = hsvToRgb(hue, 150, 255);
// writePixel(img, x, y, 0, 200, 180, 255);
writePixel(img, x, y, 0, col.r, col.g, 255);
} else {
writePixel(img, x, y, 0, 0, 0, 255);
}
}
}
}
function cross(img, x0, y0, len, r, g, b, a)
{
for(let y = y0-len; y <= y0+len; ++y)
writePixel(img, x0, y, r, g, b, a);
for(let x = x0-len; x <= x0+len; ++x)
writePixel(img, x, y0, r, g, b, a);
}
let img = createImageData(WIDTH, HEIGHT);
let changed = false;
let changeTime = 0;
function redraw()
{
txtX.text("X: " + floor(posX*1000000)/1000000);
txtY.text("Y: " + floor(posY*1000000)/1000000);
txtZoom.text("Zoom: " + floor(zoom*100)/100);
mandelbrot(img, posX, posY, zoom, 400);
cross(img, WIDTH/2, HEIGHT/2, 10, 255, 0, 0, 255);
putImageData(img, 0, 0);
changed = true;
changeTime = Date.now();
}
redraw();
Editor je nyní spuštěn v režimu pouze pro čtení. Scripty můžete s příslušným oprávněním vytvářet a editovat z
uživatelské sekce.