国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

canvas繪制經(jīng)典星空連線效果

wenzi / 3488人閱讀

摘要:點都構(gòu)建完畢了,就要構(gòu)建點與點之間的連線了,我們用到雙重遍歷,把兩個點捆綁成一組,放到數(shù)組中。最后加入鼠標(biāo)移動事件,啟動定時器大功告成

廢話不說先上圖:

關(guān)于這個效果我第一次見是在
https://www.mengxiaozhu.cn/
后來知乎登錄頁也開始用了
https://www.zhihu.com/
網(wǎng)絡(luò)上還有很多地方都在用,效果還是不錯的。
我見了之后覺得挺有意思的就研究了一下原理
下面開始coding:
先寫個canvas標(biāo)簽

加上一些默認(rèn)的樣式:

*{
    margin:0;
    padding:0;
}
body{
    overflow: hidden;
}

這里的overflow:hidden是為了防止出現(xiàn)滾動條
下面開始寫JS:
首先我們要得到那個 canvas 并得到繪制上下文:

var canvasEl = document.getElementById("canvas");
var ctx = canvasEl.getContext("2d");
var mousePos = [0, 0];

緊接著我們聲明兩個變量,分別用于存儲“星星”和邊:

var nodes = [];
var edges = [];

然后我們定義一些其他的變量:

var easingFactor = 5.0;  //緩動因子
var backgroundColor = "#000"; //背景顏色
var nodeColor = "#fff"; //點顏色
var edgeColor = "#fff"; //邊顏色
var pageWidth = window.innerWidth, //窗口寬度 
    pageHeight = window.innerHeight; //窗口高度

設(shè)置畫布的大小鋪滿整個屏幕:

window.onresize = function () {
    canvasEl.width = pageWidth;
    canvasEl.height = pageHeight;

    if (nodes.length == 0) {
        constructNodes();
    }

    render();
};

window.onresize(); 

準(zhǔn)備工作完成,我們要開始構(gòu)建點了:

function constructNodes() {
    for (var i = 0; i < 100; i++) {
        var node = {
            drivenByMouse: i == 0,
            x: Math.random() * canvasEl.width,
            y: Math.random() * canvasEl.height,
            vx: Math.random() * 1 - 0.5,
            vy: Math.random() * 1 - 0.5,
            radius: Math.random() > 0.9 ? 3 + Math.random() * 3 : 1 + Math.random() * 3
        };

        nodes.push(node);
    }

    nodes.forEach(function (e) {
        nodes.forEach(function (e2) {
            if (e == e2) {
                return;
            }

            var edge = {
                from: e,
                to: e2
            }

            addEdge(edge);
        });
    });
}

先創(chuàng)建100個點,每個點設(shè)置6個屬性,drivenByMouse屬性只有第一個點為true,其他的點為false,第一個點作為鼠標(biāo)跟隨點,不顯示出來,可以與其他點連線。x,y作為點的初始位置,取得是畫布內(nèi)的隨機點,vx,vy表示點的初始速度,范圍為-0.5到0.5之間的隨機數(shù),radius表示點的半徑,大部分的點為小的,少數(shù)的點為大的。

點都構(gòu)建完畢了,就要構(gòu)建點與點之間的連線了,我們用到雙重遍歷,把兩個點捆綁成一組,放到 edges 數(shù)組中。注意這里我用了另外一個函數(shù)來完成這件事,而沒有直接用 edges.push() ,為什么?

假設(shè)我們之前連接了 A、B兩點,也就是外側(cè)循環(huán)是A,內(nèi)側(cè)循環(huán)是B,那么在下一次循環(huán)中,外側(cè)為B,內(nèi)側(cè)為A,是不是也會創(chuàng)建一條邊呢?而實際上,這兩個邊除了方向不一樣以外是完全一樣的,這完全沒有必要而且占用資源。因此我們在 addEdge 函數(shù)中進行一個判斷:

function addEdge(edge) {
    var ignore = false;

    edges.forEach(function (e) {
        if (e.from == edge.from & e.to == edge.to) {
            ignore = true;
        }

        if (e.to == edge.from & e.from == edge.to) {
            ignore = true;
        }
    });

    if (!ignore) {
        edges.push(edge);
    }
}

至此,我們的準(zhǔn)備工作就完畢了,下面我們要讓點動起來:

function step() {
    nodes.forEach(function (e) {
        if (e.drivenByMouse) {
            return;
        }

        e.x += e.vx;
        e.y += e.vy;

        function clamp(min, max, value) {
            if (value > max) {
                return max;
            } else if (value < min) {
                return min;
            } else {
                return value;
            }
        }

        if (e.x <= 0 || e.x >= canvasEl.width) {
            e.vx *= -1;
            e.x = clamp(0, canvasEl.width, e.x)
        }

        if (e.y <= 0 || e.y >= canvasEl.height) {
            e.vy *= -1;
            e.y = clamp(0, canvasEl.height, e.y)
        }
    });

    adjustNodeDrivenByMouse();
    render();
    window.requestAnimationFrame(step);
}

function adjustNodeDrivenByMouse() {
    nodes[0].x += (mousePos[0] - nodes[0].x) / easingFactor;
    nodes[0].y += (mousePos[1] - nodes[0].y) / easingFactor;
}

這段代碼就是遍歷粒子,并且更新其狀態(tài)。根據(jù)一個簡單的物理公式 s = s + v,每次執(zhí)行都會 更新到點的下一步的狀態(tài)。
adjustNodeDrivenByMouse函將第一個點作為鼠標(biāo)的跟隨點,easingFactor為緩動因子可以讓點的運動比鼠標(biāo)運動的稍慢一點。
然后我們要讓整個粒子系統(tǒng)連續(xù)地運轉(zhuǎn)起來就需要一個timer了,但是十分不提倡大家使用 setInterval,而是盡可能使用 requestAnimationFrame,它能保證你的幀率鎖定在當(dāng)前瀏覽器的頻率下,一般為60HZ。

剩下的就是繪制了

function render() {
    ctx.fillStyle = backgroundColor;
    ctx.fillRect(0, 0, canvasEl.width, canvasEl.height);

    edges.forEach(function (e) {
        var l = lengthOfEdge(e);
        var threshold = canvasEl.width / 8;

        if (l > threshold) {
            return;
        }

        ctx.strokeStyle = edgeColor;
        ctx.lineWidth = (1.0 - l / threshold) * 2.5;
        ctx.globalAlpha = 1.0 - l / threshold;
        ctx.beginPath();
        ctx.moveTo(e.from.x, e.from.y);
        ctx.lineTo(e.to.x, e.to.y);
        ctx.stroke();
    });
    ctx.globalAlpha = 1.0;

    nodes.forEach(function (e) {
        if (e.drivenByMouse) {
            return;
        }

        ctx.fillStyle = nodeColor;
        ctx.beginPath();
        ctx.arc(e.x, e.y, e.radius, 0, 2 * Math.PI);
        ctx.fill();
    });
}
function lengthOfEdge(edge) {
    return Math.sqrt(Math.pow((edge.from.x - edge.to.x), 2) + Math.pow((edge.from.y - edge.to.y), 2));
}

繪制的時候我們要判斷線的長度如果大于某一個值,則不繪制該線了,如果在范圍之內(nèi)粗細(xì),與顏色的透明度都與線的長度相關(guān),點除了第一個鼠標(biāo)跟隨點,其他的畫入即可。
最后加入鼠標(biāo)移動事件,啟動定時器:

window.onmousemove = function (e) {
    mousePos[0] = e.clientX;
    mousePos[1] = e.clientY;
}

window.requestAnimationFrame(step);

大功告成!!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/112079.html

相關(guān)文章

  • canvas繪制經(jīng)典星空連線效果

    摘要:點都構(gòu)建完畢了,就要構(gòu)建點與點之間的連線了,我們用到雙重遍歷,把兩個點捆綁成一組,放到數(shù)組中。最后加入鼠標(biāo)移動事件,啟動定時器大功告成 廢話不說先上圖:showImg(https://segmentfault.com/img/bVOH83?w=1312&h=586); 關(guān)于這個效果我第一次見是在https://www.mengxiaozhu.cn/后來知乎登錄頁也開始用了https:/...

    hzc 評論0 收藏0
  • Canvas 點線動畫案例

    摘要:運動坐標(biāo)變量坐標(biāo)變量繪制方法畫布渲染清除畫布位置變化繪制繼續(xù)渲染動起來的多點多線動的是點,畫的是線給對象添加運動變量和兩個值表示點在軸和軸的運動量此處為在之間運動。 Canvas 點線動畫案例 畫圓: arc(x, y, r, start, stop) 畫線: moveTo(x, y) 定義線條開始坐標(biāo)lineTo(x, y) 定義線條結(jié)束坐標(biāo) 填充: fill() 繪制: stro...

    mykurisu 評論0 收藏0
  • 一步步實現(xiàn)nest粒子特效

    摘要:嘗試實現(xiàn)畫出一個彈射的小球很簡單,那怎么用多個小球?qū)崿F(xiàn)這樣的效果呢。 本文首發(fā)于我的博客,這是我的github,歡迎star。 ??這篇博客是模仿nest.js實現(xiàn)一個demo,由簡單到復(fù)雜,來一步步的實現(xiàn)它。這里是效果預(yù)覽。我的github里邊還有很多別的前端的demo,喜歡的話可以點個star,你的支持就是我的動力。 從一道面試題開始 實現(xiàn)一個半徑10px的小球在500px*5...

    ky0ncheng 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<