<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Mandelbrot</title>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<style>
canvas {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div align='center'>
<canvas id="canvas"></canvas>
</div>
<script language="JavaScript">
// Start: 2022.02.02
// Update: 2022.02.02
let cvs;
let canvas;
let bufCanvas;
let bufCtx;
let imageData;
let scaleX = 1.0;
let scaleY = 1.0;
let mx = 1.0;
let my = 1.0;
function InitCanvas() {
height = window.innerHeight;
width = window.innerWidth;
canvas = document.getElementById("canvas");
canvas.width = width;
canvas.height = height;
cvs = canvas.getContext("2d");
bufCanvas = document.createElement("canvas");
bufCanvas.width = canvas.width;
bufCanvas.height = canvas.height;
bufCtx = bufCanvas.getContext("2d");
imageData = bufCtx.createImageData(canvas.width, canvas.height);
}
function _draw(x1, y1, x2, y2) {
const MAX_COUNT = 256;
// X = -3.0 ~ 3.0
// Y = -2.0 ~ 2.0
// Z = X + Yi
mx = x1 < -3.0 ? -3.0 : x1;
my = y1 < -2.0 ? -2.0 : y1;
x2 = x2 > 3.0 ? 3.0 : x2;
y2 = y2 > 2.0 ? 2.0 : y2;
let mw = x2 - x1;
let mh = y2 - y1;
console.log(x1, y1, x2, y2, " : ", mx, my, " : ", mw, mh);
scaleX = mw / imageData.width;
scaleY = mh / imageData.height;
for (let i = 0; i < imageData.height; i++) {
for (let j = 0; j < imageData.width; j++) {
let c = 0;
let x = mx + j * scaleX;
let y = my + i * scaleY;
let sx = x;
let sy = y;
for (c = 0; c < MAX_COUNT; c++) {
if (x**2 + y**2 > 4) {
break;
}
let nx = x**2 - y**2;
let ny = 2 * x * y;
x = nx + sx;
y = ny + sy;
}
let pos = 4 * (i * imageData.width + j);
let color = 3 * c / MAX_COUNT;
if (color < 1) {
imageData.data[pos+0] = 255 * color;
imageData.data[pos+1] = color;
imageData.data[pos+2] = color;
}
else if (color < 2 ) {
imageData.data[pos+0] = 255;
imageData.data[pos+1] = color;
imageData.data[pos+2] = 0;
} else {
imageData.data[pos+0] = 255;
imageData.data[pos+1] = 255;
imageData.data[pos+2] = color;
}
imageData.data[pos+3] = 255;
}
}
bufCtx.putImageData(imageData, 0, 0);
console.log("_OnDraw2()");
}
function OnDraw() {
_draw(-3.0, -2.0, 3.0, 2.0);
cvs.clearRect(0, 0, canvas.width, canvas.height);
cvs.drawImage(bufCanvas, 0, 0);
}
function rectMouseMove(event) {
// console.log("rectMouseMove");
var currentPos = getMousePosition(event);
cvs.beginPath();
cvs.clearRect(0, 0, canvas.width, canvas.height);
cvs.drawImage(bufCanvas, 0, 0);
cvs.strokeStyle = pos.color;
var box = {
W: currentPos.X - pos.sx,
H: currentPos.Y - pos.sy
};
cvs.strokeRect(pos.sx, pos.sy, box.W, box.H);
cvs.stroke();
cvs.closePath();
}
function rectMouseUp(event) {
if (pos.isDraw) {
console.log("rectMouseUp");
var currentPos = getMousePosition(event);
pos.ex = currentPos.X;
pos.ey = currentPos.Y;
if (pos.sx > pos.ex) {
let t = pos.sx;
pos.sx = pos.ex;
pos.ex = t;
}
if (pos.sy > pos.ey) {
let t = pos.sy;
pos.sy = pos.ey;
pos.ey = t;
}
let sx = mx + pos.sx * scaleX;
let sy = my + pos.sy * scaleY;
let ex = mx + pos.ex * scaleX;
let ey = my + pos.ey * scaleY ;
_draw(sx, sy, ex, ey);
cvs.clearRect(0, 0, canvas.width, canvas.height);
cvs.drawImage(bufCanvas, 0, 0);
pos.isDraw = false;
}
}
function rectMouseDown(event) {
console.log("rectMouseDown");
if (pos.isDraw) {
return;
}
bufCtx.putImageData(imageData, 0, 0);
//bufCtx.drawImage(canvas, 0, 0);
pos.isDraw = true;
var startPos = getMousePosition(event);
pos.sx = startPos.X;
pos.sy = startPos.Y;
}
function mouseListener(event) {
switch (event.type) {
case "mousedown":
if (!pos.isDraw) {
pos.mouseDownAction(event);
}
break;
case "mousemove":
if (pos.isDraw) {
pos.mouseMoveAction(event);
}
break;
case "mouseup":
case "mouseout":
if (pos.isDraw) {
pos.mouseUpAction(event);
}
break;
}
}
function InitMouseEvent() {
canvas.addEventListener("mousedown", mouseListener);
canvas.addEventListener("mousemove", mouseListener);
canvas.addEventListener("mouseout", mouseListener);
canvas.addEventListener("mouseup", mouseListener);
}
function getMousePosition(event) {
var x = event.pageX - canvas.offsetLeft;
var y = event.pageY - canvas.offsetTop;
return { X: x, Y: y };
}
var pos = {
isDraw: false,
mouseDownAction: rectMouseDown,
mouseUpAction: rectMouseUp,
mouseMoveAction: rectMouseMove,
color: "rgb(255,211,25,255)",
sx: 0,
sy: 0,
ex: 0,
ey: 0
}
function onLoadPage() {
InitCanvas();
InitMouseEvent();
OnDraw();
}
window.onload = onLoadPage();
</script>
</body>
</html>