《朱利亚集合》随机演示图
本帖最后由 深秋红枫 于 2025-6-3 05:56 编辑 <br /><br /><!DOCTYPE html><html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>朱利亚集合 (Julia Set) 演示</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
margin: 20px;
background-color: #f0f0f0;
}
canvas {
border: 1px solid #333;
margin: 20px auto;
display: block;
background-color: white;
}
.controls {
margin: 20px;
padding: 15px;
background-color: #e0e0e0;
border-radius: 8px;
display: inline-block;
}
button {
padding: 8px 15px;
margin: 5px;
cursor: pointer;
}
input {
margin: 5px;
}
</style>
</head>
<body>
<h1>朱利亚集合 (Julia Set) 演示</h1>
<div class="controls">
<label for="real">实部 (c<sub>real</sub>):</label>
<input type="range" id="real" min="-1.5" max="1.5" step="0.01" value="-0.7">
<span id="realValue">-0.70</span><br>
<label for="imag">虚部 (c<sub>imag</sub>):</label>
<input type="range" id="imag" min="-1.5" max="1.5" step="0.01" value="0.27">
<span id="imagValue">0.27</span><br>
<label for="iterations">迭代次数:</label>
<input type="range" id="iterations" min="20" max="200" step="10" value="100">
<span id="iterationsValue">100</span><br>
<button id="draw">绘制</button>
<button id="random">随机参数</button>
</div>
<canvas id="juliaCanvas" width="600" height="600"></canvas>
<p>朱利亚集合是复平面上给定复数c后,通过迭代函数 f(z) = z² + c 不逃逸的点集。</p>
<script>
const canvas = document.getElementById('juliaCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
// 默认参数
let cReal = -0.7;
let cImag = 0.27;
let maxIterations = 100;
// 更新显示的值
document.getElementById('real').addEventListener('input', function() {
document.getElementById('realValue').textContent = this.value;
});
document.getElementById('imag').addEventListener('input', function() {
document.getElementById('imagValue').textContent = this.value;
});
document.getElementById('iterations').addEventListener('input', function() {
document.getElementById('iterationsValue').textContent = this.value;
});
// 绘制按钮
document.getElementById('draw').addEventListener('click', function() {
cReal = parseFloat(document.getElementById('real').value);
cImag = parseFloat(document.getElementById('imag').value);
maxIterations = parseInt(document.getElementById('iterations').value);
drawJuliaSet();
});
// 随机参数按钮
document.getElementById('random').addEventListener('click', function() {
cReal = (Math.random() * 2 - 1).toFixed(2);
cImag = (Math.random() * 2 - 1).toFixed(2);
document.getElementById('real').value = cReal;
document.getElementById('imag').value = cImag;
document.getElementById('realValue').textContent = cReal;
document.getElementById('imagValue').textContent = cImag;
drawJuliaSet();
});
// 绘制朱利亚集合
function drawJuliaSet() {
const imageData = ctx.createImageData(width, height);
const data = imageData.data;
// 定义绘图区域的范围(复平面)
const xMin = -2, xMax = 2;
const yMin = -2, yMax = 2;
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
// 将像素坐标映射到复平面
const zx = xMin + (xMax - xMin) * x / width;
const zy = yMin + (yMax - yMin) * y / height;
let i = 0;
let zx2 = zx, zy2 = zy;
// 迭代计算
while (zx2 * zx2 + zy2 * zy2 < 4 && i < maxIterations) {
const tmp = zx2 * zx2 - zy2 * zy2 + cReal;
zy2 = 2 * zx2 * zy2 + cImag;
zx2 = tmp;
i++;
}
// 根据迭代次数设置颜色
const idx = (x + y * width) * 4;
if (i === maxIterations) {
// 集合内的点 - 黑色
data = 0;
data = 0;
data = 0;
} else {
// 集合外的点 - 根据迭代次数设置颜色
const hue = (i / maxIterations * 360) % 360;
const saturation = 100;
const lightness = 50 + (i / maxIterations * 40);
// 将HSL转换为RGB
const rgb = hslToRgb(hue / 360, saturation / 100, lightness / 100);
data = rgb;
data = rgb;
data = rgb;
}
data = 255; // Alpha通道
}
}
ctx.putImageData(imageData, 0, 0);
}
// HSL转RGB函数
function hslToRgb(h, s, l) {
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255)
];
}
// 初始绘制
drawJuliaSet();
</script>
</body>
</html>
<br><br>
功能说明<br>
交互控制:
可以调整复数c的实部和虚部
可以设置最大迭代次数
有"绘制"按钮应用新参数
有"随机参数"按钮生成随机参数<br>
可视化效果:
朱利亚集合内的点显示为黑色
集合外的点根据逃逸时间显示不同颜色
使用HSL色彩空间生成平滑的颜色过渡<br>
数学原理:
对复平面上的每个点z,计算迭代函数f(z) = z² + c
如果迭代序列不发散(模不超过2),则该点属于朱利亚集合
发散速度决定了点的颜色
这个有点意思。{:4_199:} 老师很厉害。 这个交互运作很有趣,可以得到很多效果。{:4_204:}
代码貌似和论坛有冲突呢。
页:
[1]