Här är en realtidsrendering av mandelbrotsmängden skriven i HTML5/JS. Jag har själv en ganska slö dator, så jag ökar aldrig antalet iterationer till mer än 800, men det är lätt att korrigera. Zooma med mushjulet, panorera genom att klicka och dra. Så här ser källkoden ut:
<!DOCTYPE html>
<html lang="sv">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<title>Mandelbrot med zoom och panorering</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
justify-content: center;
-ms-align-items: center;
-o-align-items: center;
-webkit-align-items: center;
align-items: center;
background: #0000aa;
}
canvas {
border: 1px solid #4466ff;
display: block;
margin: auto;
background: #000000;
cursor: grab;
}
canvas:active {
cursor: grabbing;
}
</style>
</head>
<body>
<canvas id="canvas" width="640" height="400"></canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let width = canvas.width;
let height = canvas.height;
let xMin = -2.5, xMax = 1;
let yMin = -1.25, yMax = 1.25;
var maxIterations = 50;
let isDragging = false;
let dragStartX, dragStartY;
let dragStartXmin, dragStartXmax, dragStartYmin, dragStartYmax;
function drawMandelbrot() {
const img = ctx.createImageData(width, height);
const data = img.data;
for (let py = 0; py < height; py++) {
const y0 = yMin + (py / height) * (yMax - yMin);
for (let px = 0; px < width; px++) {
const x0 = xMin + (px / width) * (xMax - xMin);
let x = 0, y = 0, iteration = 0;
while (x * x + y * y <= 4 && iteration < maxIterations) {
const xTemp = x * x - y * y + x0;
y = 2 * x * y + y0;
x = xTemp;
iteration++;
}
const color = iteration === maxIterations ? 0 : 255 - Math.floor(iteration * 255 / maxIterations);
const index = 4 * (py * width + px);
data[index] = color;
data[index + 1] = color;
data[index + 2] = color;
data[index + 3] = 255;
}
}
ctx.putImageData(img, 0, 0);
}
drawMandelbrot();
canvas.addEventListener("wheel", function (event) {
event.preventDefault();
const mouseX = event.offsetX;
const mouseY = event.offsetY;
const zoomFactor = event.deltaY < 0 ? 0.9 : 1.1;
if (zoomFactor < 1.0) {
maxIterations += 2;
} else {
maxIterations -= 2;
}
if (maxIterations < 30) {
maxIterations = 30;
}
else if (maxIterations > 800) {
maxIterations = 800
}
const xCenter = xMin + (mouseX / width) * (xMax - xMin);
const yCenter = yMin + (mouseY / height) * (yMax - yMin);
const newWidth = (xMax - xMin) * zoomFactor;
const newHeight = (yMax - yMin) * zoomFactor;
xMin = xCenter - (mouseX / width) * newWidth;
xMax = xMin + newWidth;
yMin = yCenter - (mouseY / height) * newHeight;
yMax = yMin + newHeight;
drawMandelbrot();
});
canvas.addEventListener("mousedown", function (event) {
isDragging = true;
dragStartX = event.offsetX;
dragStartY = event.offsetY;
dragStartXmin = xMin;
dragStartXmax = xMax;
dragStartYmin = yMin;
dragStartYmax = yMax;
});
canvas.addEventListener("mousemove", function (event) {
if (!isDragging)
return;
const dx = event.offsetX - dragStartX;
const dy = event.offsetY - dragStartY;
const xShift = (dx / width) * (dragStartXmax - dragStartXmin);
const yShift = (dy / height) * (dragStartYmax - dragStartYmin);
xMin = dragStartXmin - xShift;
xMax = dragStartXmax - xShift;
yMin = dragStartYmin - yShift;
yMax = dragStartYmax - yShift;
drawMandelbrot();
});
canvas.addEventListener("mouseup", () => { isDragging = false; });
canvas.addEventListener("mouseleave", () => { isDragging = false; });
</script>
</body>
</html>

Leave a Reply