Javascript 在 canvas 上绘制分形,递归保存和恢复问题
Javascript drawing fractals on canvas, issue with recursive save and restore
我正在尝试在 canvas 上绘制大约 8 个转换,我使用的示例来自 "Sierpniski triangle" to draw my own, but I seem to be struggling whenever I increase the step size to be bigger than 1. Here is a fiddle I've got going: Current code
如果您取消注释第 43 行到第 49 行,您会看到它是如何被破坏的,但是如果您将第 14 行中的步长减小为: 1. 然后您就可以完美地看到它应该是什么样子。所以问题是我已经尝试了多种方法来保存 canvas 并恢复它,但我递归地绘制的事实让事情破裂了。
另一件事,如果您取消注释第 43 行到第 49 行以及第 40 行并保留步长:2。您几乎可以完美地看到它应该是什么样子,但事实上还有一个额外的翻转形状几乎每一次转变都使它不 "perfect".
我试过 HTML5 litten 论坛、W3S 学校并在这里搜索过,但找不到类似的东西。
我已经用下面的代码解决了这个问题:
<html>
<head>
<script type="application/javascript">
function draw(val=1) {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawT(); //Trait around the canvas (black border)
drawF(val); //draw Fractal
}
function drawF(step,color=null)
{
var toDraw=false; //Color management variable to separate 4 transformations
if (step > 0)
{
if(color) { toDraw=true; }
step = step-1;
ctx.save();
ctx.transform(0.5, 0, 0, 0.5, 250,0);
ctx.rotate(90*Math.PI/180);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#FF0000"; color="#FF0000"; }
drawF(step, color);
ctx.restore();
ctx.save();
ctx.transform(0.5, 0, 0, 0.5, 250, 0);
ctx.scale(-1, 1);
ctx.rotate(90*Math.PI/180);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#00FF00"; color="#00FF00"; }
drawF(step, color);
ctx.restore();
ctx.save();
ctx.transform(0.5, 0, 0, 0.5, 250, 250);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#0000FF"; color="#0000FF"; }
drawF(step, color);
ctx.restore();
ctx.save();
ctx.transform(0.2, 0, 0, 0.25, 250, 250);
ctx.scale(1,1);
ctx.rotate(90*Math.PI/180);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#FFFF00"; color="#FFFF00"; }
drawF(step, color);
ctx.restore();
} else {
drawShape();
}
}
function drawT() {
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(500,0);
ctx.lineTo(500,500);
ctx.lineTo(300,500);
ctx.lineTo(300,400);
ctx.lineTo(150,400);
ctx.lineTo(150,250);
ctx.lineTo(0, 250);
ctx.closePath();
ctx.stroke();
}
function drawShape() {
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(500,0);
ctx.lineTo(500,500);
ctx.lineTo(300,500);
ctx.lineTo(300,400);
ctx.lineTo(150,400);
ctx.lineTo(150,250);
ctx.lineTo(0, 250);
ctx.closePath();
ctx.fill();
}
}
function showVal(newVal){
draw(newVal);
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<input type="range" min="1" max="7" step="1" value="1"
oninput="showVal(this.value)" onchange="showVal(this.value)">
</html>
使用滑块进行转换过程。
我正在尝试在 canvas 上绘制大约 8 个转换,我使用的示例来自 "Sierpniski triangle" to draw my own, but I seem to be struggling whenever I increase the step size to be bigger than 1. Here is a fiddle I've got going: Current code
如果您取消注释第 43 行到第 49 行,您会看到它是如何被破坏的,但是如果您将第 14 行中的步长减小为: 1. 然后您就可以完美地看到它应该是什么样子。所以问题是我已经尝试了多种方法来保存 canvas 并恢复它,但我递归地绘制的事实让事情破裂了。
另一件事,如果您取消注释第 43 行到第 49 行以及第 40 行并保留步长:2。您几乎可以完美地看到它应该是什么样子,但事实上还有一个额外的翻转形状几乎每一次转变都使它不 "perfect".
我试过 HTML5 litten 论坛、W3S 学校并在这里搜索过,但找不到类似的东西。
我已经用下面的代码解决了这个问题:
<html>
<head>
<script type="application/javascript">
function draw(val=1) {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawT(); //Trait around the canvas (black border)
drawF(val); //draw Fractal
}
function drawF(step,color=null)
{
var toDraw=false; //Color management variable to separate 4 transformations
if (step > 0)
{
if(color) { toDraw=true; }
step = step-1;
ctx.save();
ctx.transform(0.5, 0, 0, 0.5, 250,0);
ctx.rotate(90*Math.PI/180);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#FF0000"; color="#FF0000"; }
drawF(step, color);
ctx.restore();
ctx.save();
ctx.transform(0.5, 0, 0, 0.5, 250, 0);
ctx.scale(-1, 1);
ctx.rotate(90*Math.PI/180);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#00FF00"; color="#00FF00"; }
drawF(step, color);
ctx.restore();
ctx.save();
ctx.transform(0.5, 0, 0, 0.5, 250, 250);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#0000FF"; color="#0000FF"; }
drawF(step, color);
ctx.restore();
ctx.save();
ctx.transform(0.2, 0, 0, 0.25, 250, 250);
ctx.scale(1,1);
ctx.rotate(90*Math.PI/180);
if(toDraw) { ctx.fillStyle=color; }
else { ctx.fillStyle="#FFFF00"; color="#FFFF00"; }
drawF(step, color);
ctx.restore();
} else {
drawShape();
}
}
function drawT() {
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(500,0);
ctx.lineTo(500,500);
ctx.lineTo(300,500);
ctx.lineTo(300,400);
ctx.lineTo(150,400);
ctx.lineTo(150,250);
ctx.lineTo(0, 250);
ctx.closePath();
ctx.stroke();
}
function drawShape() {
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(500,0);
ctx.lineTo(500,500);
ctx.lineTo(300,500);
ctx.lineTo(300,400);
ctx.lineTo(150,400);
ctx.lineTo(150,250);
ctx.lineTo(0, 250);
ctx.closePath();
ctx.fill();
}
}
function showVal(newVal){
draw(newVal);
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="500" height="500"></canvas>
</body>
<input type="range" min="1" max="7" step="1" value="1"
oninput="showVal(this.value)" onchange="showVal(this.value)">
</html>
使用滑块进行转换过程。