做者:javascript
翻译:疯狂的技术宅css
原文:slicker.me/javascript/…html
未经容许严禁转载前端
我曾经用 Python 海龟图形生成过这个图像,并有用 JavaScript 复制它的强烈冲动。java
对于那些不熟悉海龟图形的人来讲,这是一个使用虚拟“海龟”绘制图形的概念,当海龟四处移动时,它的尾巴会在屏幕上留下痕迹。海龟有几个简单的命令:向前/向后移动 x 步,向左/向右转 x 度等。编程
因此例如这个序列:canvas
会画一个正方形。每次移动后,乌龟的位置和方向都会更新,下一步移动将相对于以前的位置。有点相似于Canvas Path(你能够有一系列的 lineTo),但 Path 只能使用笛卡尔坐标(x 和 y)而不是方向(左/右/前/后)。前端工程化
若是海龟朝北开始,左转 90 度它将指向西。再左 90 度会指向南等。数组
能够在 Logo(自20世纪60年代)和 Python 中使用海龟图形,但不能在 JavaScript 中使用。函数
但真的是这样吗?我忽然意识到 context.rotate
基本上模仿 “左转/右转”,而 context.translate
与 moveTo/drawTo
结合起来就像“前进/后退”同样。
这绝对不是一种优雅或可扩展的图形编程方式 —— 有点像用蚯蚓绑鞋子:它看起来很酷,但只适用于某些条件。这些只是个人奇怪代码集中的另外一个小发明。若是你玩真正的海龟图形,我建议你使用提供这种功能的 JS 库、Python 或 Logo。或者至少先建立移动和旋转海龟的功能,以便使你的代码可读。
个人第一反应是建立一个具备本身的坐标和方向的海龟对象,而后使用 trig
函数计算移动,可是 rotate/translate 解决方案确定更有趣,并容许我几乎逐行翻译 Python 程序:
首先,让咱们看一下 rotate 和 translate 方法的工做原理。他们基本上改变了坐标系:
It's easiest to see it in an example: 经过下面这个例子中最容易理解:
<html>
<style> body { background-color: black;} </style>
<body>
<canvas id='myCanvas' width='800' height='600'></canvas>
<script> function line(x1, y1, x2, y2) { context.beginPath(); context.moveTo(x1, y1); context.lineTo(x2, y2); context.stroke(); } function drawAxles() { line(-length, 0, length, 0); // x axis line(length * .9, length * .1, length, 0); line(length * .9, -length * .1, length, 0); line(0, -length, 0, length); // y axis line(-length * .1, length * .9, 0, length); line(length * .1, length * .9, 0, length); } let length = 100; let canvas = document.getElementById('myCanvas'); let context = canvas.getContext('2d'); context.strokeStyle = 'white'; drawAxles(); context.translate(length * 3, length); context.strokeStyle = 'blue'; drawAxles(); context.rotate(Math.PI / 8); context.strokeStyle = 'red'; drawAxles(); context.translate(3 * length, 0); context.strokeStyle = 'green'; drawAxles(); </script>
</body>
复制代码
左上角的白色(半)箭头是 HTML5 Canvas 的标准初始 X(水平)和 Y 轴(垂直)。注意,Y 轴指向下方 —— 与你在学校学到的笛卡尔坐标系相反。
轴的负部分位于屏幕以外。
如今咱们用 translate 来向右和向下移动坐标系 —— 也就是这些蓝色箭头。
接下来,咱们将坐标系旋转几度并绘制红色箭头。请注意,原点(0, 0)仍然与蓝色原点位于同一位置。
最后,咱们将系统在 x 轴上移动并将其绘制为绿色。请注意,上一步的轮换仍然适用。
如今让咱们看看原始 Python 代码的 JavaScript 版本:
<html>
<style> body { background-color: black;} </style>
<canvas id='myCanvas' width='800' height='600'></canvas>
<body>
<script> let colors = ['red', 'purple', 'blue', 'green', 'orange', 'yellow']; let canvas = document.getElementById('myCanvas'); let context = canvas.getContext('2d'); context.scale(.3, .3); context.translate(canvas.width, canvas.height); for (let i = 0; i < 360; i++) { context.strokeStyle = colors[i % 6]; context.lineWidth = i / 100 + 1; context.beginPath(); context.moveTo(0, 0); context.lineTo(0, i); context.stroke(); context.translate(0, i); context.rotate(-59 * (2 * Math.PI / 360)); } </script>
</body>
</canvas>
复制代码
在第[11]行中,我缩小了图像。不然若是我保留原始的 Python 维度,它将会很是大。
[12] 将“海龟”移到画布的右下角。
[13-22] 绘制螺旋的主循环
[14]经过颜色数组([8])循环
[15]随着螺旋的增加改变线宽。它几乎不可见。
[16-20] 经过 i
步长向前移动海龟。 [16-19] 画线,[20] 移动海龟。因此咱们首先绘制线,并在过后更新“海龟”的位置。
当海龟离开中心时,线的长度变长。
[21] 将海龟旋转 59 度。负号只是为了保持螺旋方向。
如今让咱们把螺旋旋转一下。只需几行代码就能够改变海龟转动的角度。我使用正弦函数[10]来实现,但若是你不是三角函数的粉丝,也能够使用不一样的公式。甚至像 let rotation = counter / speed;
这样简单的东西产生有趣的结果(确保根据本身的喜爱调整 [32] 中的速度)。
<html>
<style> body { background-color: black;} </style>
<body>
<canvas id='myCanvas' width='800' height='600'></canvas>
<script> function animate() { let rotation = (2 * Math.sin(counter / (3.14 * speed))); context.setTransform(scale, 0, 0, scale, canvas.width / 2, canvas.height / 2); context.clearRect(-canvas.width / 2, -canvas.height, canvas.width, canvas.height *2); for (let i = 0; i < 360; i++) { context.strokeStyle = colors[i % 6]; context.lineWidth = i / 100 + 1; context.beginPath(); context.moveTo(0, 0); context.lineTo(0, i); context.stroke(); context.translate(0, i); context.rotate((-60 + rotation) * 2 * Math.PI / 360); } window.requestAnimationFrame(animate); counter++; } let colors = ['red', 'purple', 'blue', 'green', 'orange', 'yellow']; let canvas = document.getElementById('myCanvas'); let context = canvas.getContext('2d'); let counter = 0; let scale = .3; let speed = 20; animate(); </script>
</canvas>
</body>
复制代码
如下这些参源能够帮你了解更多图形学方面的东西:
Spinning squares - visual effect (25 lines)
Oldschool fire effect (20 lines)
Physics engine - interactive sandbox
Physics engine - silly contraption
Yin Yang with a twist (4 circles and 20 lines)
Image transition effect (16 lines)
Wholla lotta quadratic curves (50 lines)
Your first program in JavaScript: you need 5 minutes and a notepad