1. 程式人生 > >js實現蕨類植物葉子,葉子分形圖形

js實現蕨類植物葉子,葉子分形圖形

doc ren pat fill ret () and .get AS

分形圖形很是奇妙,這裏展示的是蕨類植物葉子的分形圖形。

這裏使用Canvas 通過描點的方式來繪制圖形,先說一下原理:

先來個方程:

技術分享圖片

或許看完這個覺得很懵逼,這裏就不說這個方程怎麽計算了。由這個方程可以得到 8個式子,兩兩一組有四組

第一組函數:

f(x, y) = 0

f(x, y) = 0.16y

第二組函數:

f(x, y) = 0.2x - 0.26y

f(x, y) = 0.23x + 0.22y +1.6

第三組函數:

f(x, y) = -0.15x +0.28y

f(x, y) = 0.26x +0.24y +0.44

第四組函數:

f(x, y) = 0.85x +0.04y

f(x, y) = -0.04x + 0.85y +1.6

得到這四組式子後,我們需要隨機抽取一組(抽取概率為,第一組1% ,第二組7% , 第三組7% 第四組百分之85%

先隨機兩個隨機出數x0和y0放進這一組中計算,每一組的第一個式子代入x0和y0進去得到的f(x,y) 也就是得到的結果,作為x1,

第二個式子代入x0和y0得到的結果y1。

拿到x1和y1後在和上面規則一樣,在隨機出一組式子,和上面一樣,把x1和y1分別代入進去隨機出來的哪一組式子的第一個式子和第二個式子得出x2和y2,

這個過程重復20次左右會得到x20 和y20,這個x20和y20我們就作為點的坐標給描出來。這樣就叠代得到一個點,要20000個點就重復20000次(也差不多這麽多點描出來的葉子才好看)。

如果你把第一組的得出的x1和y1代入後 下面沒有隨機一組式子,叠代20次就會得到下面的圖形

技術分享圖片

當然照著上面的做法完了後會得到什麽,你會看見你屏幕上什麽都沒有,或許還是有一點點的

技術分享圖片

這時候我們在最後ctx.fillRect(x, y, 1, 1)的x坐標和y坐標都加500,意思x坐標移動500 y坐標移動500。然後圖在中間了,但是還是看不見那麽在這樣

ctx.fillRect(x*30+500, y*30+500, 1, 1)給*30放大

技術分享圖片

你會發現TMD倒著的。這時候改改ctx.fillRect(x*30+500, - y*30+500, 1, 1) 在y前面加負號,還可以ctx.fillRect(-x*30+500, - y*30+500, 1, 1)在x前面加負號看看

技術分享圖片 技術分享圖片

上面標紅的地方你可以試試調調數字有些會有特別的圖。這裏我把第三組式子的概率調到了40.

技術分享圖片

你還可以試著改改上面的那幾組式子,或者添加新的式子,得到一些新的,圖形。這裏我就沒有測試了。

下面放上源碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>QAQ</title>
<style>
body {
    padding: 0;
    margin: 0
} 
#mycanvas {
    margin:20px; 
}
</style>
</head>
<body>
    <canvas id="mycanvas" width="2048px" height="1266px" style="background-color:black;"></canvas>
<script>
var mycanvas = document.getElementById("mycanvas");
    mycanvas.width = 2048;
    mycanvas.height = 1266;
    var ctx = mycanvas.getContext(2d);
        ctx.clearRect(0, 0, 2048, 1266);
        ctx.fillStyle = "#0f0";      
        pwowq = {
            F1: [
              (function(x, y) {
                return 0;
              }), (function(x, y) {
                return 0.16 * y;
              })
            ],
           F2: [
              (function(x, y) {
                return 0.2 * x - 0.26 * y;
              }), (function(x, y) {
                return 0.23 * x + 0.22 * y + 1.6;
              })
            ],
            F3: [
                (function(x, y) {
                  return -0.15 * x + 0.28 * y;
                }), (function(x, y) {
                  return 0.26 * x + 0.24 * y + 0.44;
                })
             ],
            F4: [
              (function(x, y) {
                return 0.85 * x + 0.04 * y;
              }), (function(x, y) {
                return -0.04 * x + 0.85 * y + 1.6;
              })
            ],
        }

    
var newArr = []

for(let i = 0; i < 1; i++){
  newArr.push(pwowq.F1)
}
for(let ii = 0;ii<7; ii++){
    newArr.push(pwowq.F2)
}
for(let iii = 0;iii<7;iii++){
    newArr.push(pwowq.F3)
}
for(let iiii = 0; iiii<85; iiii++){
    newArr.push(pwowq.F4)
}

var count = 0;
render = function() {
    var  QAQ;
    var  f;
    var  x = Math.random();
    var  y = Math.random();
   // for (var i = 0;i<10000 ;i++) {
      for(var jj = 0; jj < 20; jj++) {
       f = newArr[~~(Math.random()*100)];//或者f = parseInt(Math.random()*100)
        QAQ = [f[0](x, y), f[1](x, y)];
        x = QAQ[0];
        y = QAQ[1];
      }
      ctx.fillRect(x*30+500, -y*30+500, 1, 1);/*渲染點*/
    
    if(count < 10000){
       window.requestAnimationFrame(render)
      // window.requestAnimationFrame(render)//取消註釋以雙倍的速度渲染
       count++
     }
   // }
  };
//render()
window.requestAnimationFrame(render);

</script>    
</body>
</html>

js實現蕨類植物葉子,葉子分形圖形