翻譯:瘋狂的技術宅原文:https://slicker.me/javascript...javascript
未經容許嚴禁轉載html
我曾經用 Python 海龜圖形生成過這個圖像,並有用 JavaScript 複製它的強烈衝動。前端
對於那些不熟悉海龜圖形的人來講,這是一個使用虛擬「海龜」繪製圖形的概念,當海龜四處移動時,它的尾巴會在屏幕上留下痕跡。海龜有幾個簡單的命令:向前/向後移動 x 步,向左/向右轉 x 度等。java
因此例如這個序列:程序員
會畫一個正方形。每次移動後,烏龜的位置和方向都會更新,下一步移動將相對於以前的位置。有點相似於Canvas Path(你能夠有一系列的 lineTo),但 Path 只能使用笛卡爾座標(x 和 y)而不是方向(左/右/前/後)。面試
若是海龜朝北開始,左轉 90 度它將指向西。再左 90 度會指向南等。編程
能夠在 Logo(自20世紀60年代)和 Python 中使用海龜圖形,但不能在 JavaScript 中使用。canvas
但真的是這樣嗎?我忽然意識到 context.rotate
基本上模仿 「左轉/右轉」,而 context.translate
與 moveTo/drawTo
結合起來就像「前進/後退」同樣。segmentfault
這絕對不是一種優雅或可擴展的圖形編程方式 —— 有點像用蚯蚓綁鞋子:它看起來很酷,但只適用於某些條件。這些只是個人奇怪代碼集中的另外一個小發明。若是你玩真正的海龜圖形,我建議你使用提供這種功能的 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