使用canvas 绘制斐波那契螺旋线(斐波那契数列的应用)

在文章的开头,我们先来认识一下斐波那契数列
斐波那契数列 又被称作是 兔子数列

e.g. 1、1、2、3、5、8、13、21、34、…

从上面的例子可以看出斐波那契数列的规律,就是从第三个数开始,每个数的值都是它前两个数之和。

再来看一下例子程序:

function getFibonacci(n) {
    let arr = []
    let i = 0
    while (i < n) {
        if (i <= 1) {
            arr.push(i)
        }else {
            arr.push(arr[i - 1] + arr[i - 2])
        }
        i++
    }
    return arr
}

知道了斐波那契数列 之后怎么用呢?今天来教你使用Canvas 来绘制斐波那契螺旋线

先来看一张斐波那契螺旋线 的图片
使用canvas 绘制斐波那契螺旋线(斐波那契数列的应用)_第1张图片

我们要画的就是上图中的曲线。
现在开始贴代码,代码中的难点都带有注释。

let ctx = canvas.getContext('2d')
ctx.beginPath();
ctx.arc(300, 240, 5, Math.PI, 0.5 * Math.PI, true);
ctx.arc(300, 235, 10, Math.PI * 0.5, 0, true);
ctx.arc(295, 235, 15, 0, Math.PI * 1.5, true);
ctx.arc(295, 245, 25, Math.PI * 1.5, Math.PI, true);
ctx.arc(310, 245, 40, Math.PI, Math.PI * 0.5, true);
ctx.arc(310, 220, 65, Math.PI * 0.5, 0, true);
ctx.arc(270, 220, 105, 0, Math.PI * 1.5, true);
ctx.arc(270, 285, 170, Math.PI * 1.5, Math.PI, true);
ctx.strokeStyle = '#fff'
ctx.stroke();

上面的代码是利用Canvas 直接画螺旋线的代码。
可以作为下面利用斐波那契数列 画螺旋线的代码的参考

let canvas = document.getElementsByTagName('canvas')[0]
canvas.width = 600
canvas.height = 480
let coor = {
    x: 300,
    y: 240,
}
//先取背景图中的中间点作为一开始的圆点

let ctx = canvas.getContext('2d')
//获取该canvas的2D绘图环境对象

/*
绘制曲线方法
@param prevR 这是斐波那契数列中前一位的数值,也就是上一截曲线的半径
@param n 这是斐波那契数列中的下标
@param r 这是斐波那契数列当前下标的值,也就是将画曲线的半径
*/
function draw(prevR, n, r) {
    let radius = r * 5 
    //五倍半径画,不然太小了

    let startAngle = Math.PI
    let endAngle = Math.PI * 0.5
    //每个半径只画1/4个圆,所以开始角度和结束角度刚好相差 1/4 * PI

    let anticlockwise = true
    //设置为逆时针方向画

    //改变圆点坐标、开始角度和结束角度
    //第三个元素的圆点坐标、开始角度和结束角度上面已经给出,所以从第四个元素开始改变圆点坐标、开始角度和结束角度,也就是从n > 2开始
    if (n > 2) {
        //下面坐标的改变可以参考上面的图和直接用canvas画的代码。
        switch(n % 4) {
            case 0:
                coor.x = coor.x + (5 * prevR) - radius
                startAngle = 0
                endAngle = Math.PI * 1.5
                break;
            case 1:
                coor.y = coor.y - (5 * prevR) + radius
                startAngle = Math.PI * 1.5
                endAngle = Math.PI
                break;
            case 2:
                coor.x = coor.x - (5 * prevR) + radius
                startAngle = Math.PI
                endAngle = Math.PI * 0.5
                break;
            case 3:
                coor.y = coor.y + (5 * prevR) - radius
                startAngle = Math.PI * 0.5
                endAngle = 0
                break;
        }
    }
    ctx.beginPath()
    ctx.arc(coor.x, coor.y, radius, startAngle, endAngle, anticlockwise)
    ctx.lineWidth = 1
    ctx.strokeStyle = '#fff'
    ctx.stroke()
}
//获取斐波那契数列
function getFibonacci(n) {
    let arr = []
    let i = 0
    while (i < n) {
        if (i <= 1) {
            arr.push(i)
        }else {
            arr.push(arr[i - 1] + arr[i - 2])
        }
        i++
    }
    return arr
}
let fibonacci = getFibonacci(10)
for (let i = 0; i < fibonacci.length; i++) {
    //从第三个元素开始画,符合斐波那契数列的规律
    if (i >= 2) {
        draw(fibonacci[i - 1], i, fibonacci[i])
    }
}

—–我是分隔线—–
最终画出来的效果可以看下面这个链接:
Fibonacci spiral

你可能感兴趣的:(algorithm)