婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 如何使用canvas繪制可移動網格的示例代碼

如何使用canvas繪制可移動網格的示例代碼

熱門標簽:拓展地圖標注 平涼地圖標注位置怎么弄 高德地圖標注地點糾錯 電話機器人電銷系統掙話費 機器人外呼系統存在哪些能力 如何獲取地圖標注客戶 電話機器人黑斑馬免費 只辦理400電話 南昌仁和怎么申請開通400電話

本文主要介紹了如何使用canvas繪制可移動網格的示例代碼,分享給大家,具體如下:

效果

說明

這個是真實項目中遇到的需求,我把它抽離出來,屏蔽了那些業務相關的東西,僅從代碼角度來考慮這個問題。首先網格大小可配置,每個頂點是可以移動的。看到這個問題,不知道各位是怎么去思考的。就先來說說我自己的思路。

分析

首先需要有一個起點,這樣就能確定網格所在的位置,其次就是網格中的每個正方形(我們就按正方形來思考,這樣簡單一點)的邊長是多少,另外每個頂點移動的時候,邊也需要跟著移動。

所以其實要存儲的就只有兩類對象,一類就是線,另外就是頂點。

如何存儲頂點和線呢?這里用了一個庫fabric.js,就比較容易的創建頂點和邊的對象,并且它也提供了移動邊的方法,但是問題也同時出現了:按照上面的顯示,一個點最多關聯4條邊,最少也關聯了2條邊,如何表示這種頂點和邊的關聯關系呢?

先想到就是使用數組來存儲頂點和線,然后再根據線中包含的頂點坐標來判斷這個線是否和某個頂點相連,如果是的話,則將將其加入到頂點的關聯屬性中。后面當移動頂點的時候,根據頂點拿到其關聯的線,去動態改變線的坐標,這樣就能實現上面的那種效果了。

實現

下面根據以上分析,我們來實現代碼。首先需要存儲的對象有頂點、邊。然后根據起點坐標以及每個小矩形的邊長,很容易就可以計算出所有的頂點坐標。

function Grid({node, unit, row, col, matrix = []}) {
    // 存儲頂點
    this.vertexes = [];
    // 存儲邊
    this.lines = [];
    
    // 根據起點坐標以及單位邊長計算
    for (let i = 0; i <= row; i++) {
        for (let j = 0; j <= col; j++) {
            const newVertex = makeRect(node.x + i * unit, node.y + j * unit);
            this.vertexes.push(newVertex);
        }
    }
    
    // 添加頂點對象的事件監聽器
    this.addListener();
}

那么邊怎么計算呢,構造邊的話,只需要兩個頂點就可以連成邊,因此我們可以選擇遍歷頂點來構造邊,但是這樣的話會造成重復的邊,而我們只需要一條邊就可以了,不然移動的話,你會發現移動完,下面還會顯示一條重疊的邊。當然其實最重要的原因就是效率問題,如果不去重的話,會導致計算的時間復雜度過高。

現在有兩種方法來解決,一種就是給頂點做標記,當前做線的兩端的頂點已經標記過了,那么就跳過當前輪的遍歷。另外一種方法,就是可以根據網格這種特定的形狀來獲取邊,如下圖,按照兩種不同的顏色來計算水平的邊和垂直的邊。

這樣的話,水平方向,就每行兩兩構成邊,垂直方向,就按照一定的間隔連接兩個頂點構成邊。這里因為后面需要傳給算法的格式是二維數組,因此就使用了這個方法。

// ...省略了

// 構造矩陣
this.matrix = [];
let index = -1;
for (let i = 0; i < this.vertexes.length; i++) {
    if (i % (col + 1) === 0) {
        index++;
        this.matrix[index] = [];
    }
    this.matrix[index].push(this.vertexes[i]);
}

// 根據矩陣添加邊
let idx = 0;
for (let i = 0; i < this.matrix.length; i++) {
    for (let j = 0; j < this.matrix[i].length; j++) {
        // 交叉渲染邊,這樣能夠在可視區內優先展示
        this.matrix[i][j+1] && this.makeLine(this.matrix[i][j], this.matrix[i][j+1]);
        this.vertexes[idx + col + 1] &&
            this.makeLine(this.vertexes[idx], this.vertexes[idx + col + 1]);
        idx++;
    }
}

后面就是找每個頂點關聯了幾條邊

for (let i = 0; i < this.vertexes.length; i++) {
  const vertex = this.vertexes[i];
  // 根據頂點的坐標是否是邊的兩端的開始或結束坐標來判斷頂點是否與這條邊關聯
  const associateLines = this.lines.filter(item => {
    return (item.x1 === vertex.left && item.y1 === vertex.top) ||
      (item.x2 === vertext.left && item.y2 === vertex.top);
  });
  vertex.lines = associateLines;
}

眼精的同學肯定一眼就看出來啦,這個時間復雜度太高了。所以雖然網格畫出來了,但是當頂點數量過多的時候,計算時間太長,導致瀏覽器卡住了了差不多2s往上,當水平方向有50個頂點,垂直方向有50個頂點,就能明顯看到瀏覽器的卡頓,此時如果有輸入框之類的交互UI,是無法做任何操作的,這肯定也是不行滴。

改進

那么有什么方法能夠高效的找到頂點和邊之間的關聯呢?這里就不賣關子了,當然可能還有其他更好的方法,但是筆者知識所限,只能到這啦。

解決辦法就是圖這種結構,因為圖的邊可以使用鄰接表或者是鄰接矩陣來存儲,這樣如果我存儲了一個頂點,那么與這個頂點關聯的邊其實就確定了,也就是說,我們在添加頂點的時候,就順便解決了這種頂點的關聯問題,不再需要再次遍歷所有的邊來找關聯了。(這里就不詳細介紹圖這種數據結構了,有興趣的同學可以自己查找資料,實際這里運用圖的地方也就是這個邊和頂點的關聯關系,其他什么圖的遍歷都沒有用到)

我們來改進一下我們的代碼。

function Grid({node, unit, row, col, matrix = []}) {
    this.vertexes = [];
    this.lines = [];
    this.edges = new Map();

    this.addEdges = addEdges;
    this.addVertexes = addVertexes;
}

這里添加了一個新的屬性edges,來存儲頂點和邊的映射關系。其他的步驟和先前都是一樣的,只是更換了添加頂點和邊的方法,什么意思呢,看代碼其實明白了:

function Grid({node, unit, row, col, matrix = []}) {
    // ...省略

    // 根據矩陣添加邊
    let idx = 0;
    for (let i = 0; i < this.matrix.length; i++) {
        for (let j = 0; j < this.matrix[i].length; j++) {
            // 交叉渲染邊,這樣能夠在可視區內優先展示
            this.matrix[i][j+1] && this.addEdges(this.matrix[i][j], this.matrix[i][j+1]);
            this.vertexes[idx + col + 1] &&
                this.addEdges(this.vertexes[idx], this.vertexes[idx + col + 1]);
            idx++;
        }
    }

    // 將邊關聯到頂點
    this.edges.forEach((value, key) => {
        key.lines = value;
    });
}

這里我們就將復雜度為O(mn)的計算降低為了O(n),這里mlines的長度,nvertexes的長度。然后再來看下此時計算100*100的頂點數,計算時間只有200ms,已經能夠滿足我的需求了。那么圖是如何實現這種關聯的呢,其實就是每次添加邊的時候,將邊的兩個頂點同時添加進關聯關系中,也就是Map的結構中。

function addEdges(v, w) {
    const line = makeLine({point1: v, point2: w});
    // 頂點v關聯了邊line
    this.edges.get(v).push(line);
    // 頂點w也同時關聯了邊line
    this.edges.get(w).push(line);
    this.lines.push(line);
}

function addVertexes(v) {
    this.vertexes.push(v);
    // 給每個頂點設置一個Map結構
    this.edges.set(v, []);
}

這樣計算完所有的頂點之后,實際頂點關聯的邊也都確定了,最后只需要遍歷一下這些edges就可以了。

完成了這些之后,開開心心的調用fabric的api,將這些對象添加進canvas中就可以了。

// fabric的API,添加fabric對象到畫布中
canvas.add(...this.vertexes);
canvas.add(...this.lines);

好了,大功告成,可以交差了。運行頁面,打開一看,好家伙,計算速度是快了很多,但是渲染的速度慘不忍睹,30*30的頂點數量,頁面還是有卡頓的情況,這是怎么回事呢?

仔細想想,添加這么多的對象到畫布中,計算量確實是非常大的,但是這里我們也無法改變這種渲染消耗。于是想到了一個折中的方法,就是利用時間切片,簡單來說,就是利用requestAnimationFrame這個API,將渲染任務分割為一個一個的片段,在瀏覽器空閑時去渲染,這樣就不會去阻塞其他瀏覽器的任務。這里就涉及了一些瀏覽器渲染的相關知識。

function renderIdleCallback(canvas) {
    // 任務切片
    const points = this.points.slice();
    const lines = this.lines.slice();
    const task = () => {
        // 清理canvas的時候,中斷后面的渲染
        if (this.interrupt) return;
        if (!points.length && !lines.length) return;
        let slicePoint = [], sliceLine = [];
        for (let i = 0; i < 10; i++) {
            if (points.length) {
                const top = points.shift();
                slicePoint.push(top);
            }
            if (lines.length) {
                const top = lines.shift();
                sliceLine.push(top);
            }
        }
        canvas.add(...slicePoint);
        canvas.add(...sliceLine);
        window.requestAnimationFrame(task);
    }
    task();
}

上面的代碼加入了一個標識符來中斷渲染,因為存在這樣一種情況,本次網格還沒有渲染完,就被清理掉又重新渲染,那么就需要停止上次的渲染,重新開始新的渲染了。

總結

好了,到這里也就結束了。由于筆者知識淺薄,只能做到這種滿足需求的優化了,更極致的優化就要看各位大佬指點。同時此次嘗試也是筆者第一次將所學的數據結構、優化手段結合到項目中,成就感還是非常多的,也是感受到數據結構算法對于程序員的重要性,如果想要突破自己的技術瓶頸,那么這也是繞不開的一個點。

到此這篇關于如何使用canvas繪制可移動網格的示例代碼的文章就介紹到這了,更多相關canvas 可移動網格內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章,希望大家以后多多支持腳本之家!

標簽:遼源 永州 棗莊 青島 西藏 漯河 新疆 池州

巨人網絡通訊聲明:本文標題《如何使用canvas繪制可移動網格的示例代碼》,本文關鍵詞  如何,使用,canvas,繪制,可移動,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《如何使用canvas繪制可移動網格的示例代碼》相關的同類信息!
  • 本頁收集關于如何使用canvas繪制可移動網格的示例代碼的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    欧美日韩美女一区二区| 久久伊人中文字幕| 日韩片之四级片| 亚洲欧美国产高清| 国产一区二区三区蝌蚪| 东方欧美亚洲色图在线| 日韩亚洲国产中文字幕欧美| 艳妇臀荡乳欲伦亚洲一区| 不卡一区在线观看| 精品少妇一区二区三区| 午夜婷婷国产麻豆精品| 99久久精品免费观看| 国产精品天干天干在观线| 久久99久久99精品免视看婷婷| 欧美日韩成人激情| 亚洲精品久久7777| 99视频一区二区三区| 国产欧美久久久精品影院| 久草热8精品视频在线观看| 欧美性xxxxxx少妇| 国产精品乱人伦| 国产精品18久久久久| 欧美zozo另类异族| 免费不卡在线视频| 欧美一区二区三区免费视频 | 麻豆91在线播放| 欧美日韩在线免费视频| 一区二区三区在线免费| 99r精品视频| 亚洲色图.com| av亚洲精华国产精华精| 国产精品久线在线观看| 成人精品免费网站| 欧美极品少妇xxxxⅹ高跟鞋| 国产成人精品亚洲777人妖| 国产视频一区在线观看| 国产成人啪免费观看软件| 国产午夜久久久久| 国产不卡视频在线播放| 亚洲欧洲一区二区三区| 91老师片黄在线观看| 亚洲人一二三区| 欧美日韩中文字幕一区| 日本中文字幕一区| 日韩亚洲欧美在线观看| 狠狠色狠狠色综合| 国产精品网曝门| 色哟哟一区二区在线观看| 午夜精品久久久| 精品美女在线观看| 粉嫩欧美一区二区三区高清影视| 中文字幕一区三区| 欧美性大战xxxxx久久久| 秋霞午夜av一区二区三区| 久久蜜桃av一区精品变态类天堂 | 日韩一级高清毛片| 国产suv一区二区三区88区| 亚洲欧美另类小说视频| 欧美高清性hdvideosex| 激情小说欧美图片| 国产精品成人一区二区艾草| 欧美日韩一区二区在线观看视频 | 国产精品夫妻自拍| 欧美日韩国产欧美日美国产精品| 久久精品国产一区二区三 | 欧美日韩免费电影| 国产高清亚洲一区| 亚洲自拍与偷拍| 久久久精品综合| 欧美午夜电影网| 国产精品自拍在线| 三级一区在线视频先锋| 国产精品视频线看| 在线播放视频一区| 97久久精品人人做人人爽50路| 午夜精品免费在线观看| 中文字幕二三区不卡| 欧美三级一区二区| 成人精品电影在线观看| 日韩精品成人一区二区在线| 国产精品素人视频| 欧美精品一区二| 欧美日韩国产一级二级| 91原创在线视频| 国产成人三级在线观看| 男女视频一区二区| 夜夜精品视频一区二区| 国产精品免费视频一区| 久久综合九色综合欧美亚洲| 欧美日韩综合一区| 色综合久久九月婷婷色综合| 粉嫩高潮美女一区二区三区| 老鸭窝一区二区久久精品| 亚洲最新视频在线播放| 亚洲欧美色综合| 一区在线中文字幕| 中文字幕不卡在线播放| 欧美电影免费观看高清完整版在线 | 精品粉嫩超白一线天av| 91麻豆精品91久久久久同性| 色婷婷综合久久久久中文一区二区| 国产寡妇亲子伦一区二区| 国产综合色在线视频区| 日日夜夜免费精品| 午夜一区二区三区在线观看| 亚洲素人一区二区| 中文字幕欧美一| 中文字幕视频一区二区三区久| 亚洲国产精品精华液2区45| 久久久久9999亚洲精品| 久久久99精品免费观看| 久久久电影一区二区三区| 亚洲精品一线二线三线| 日韩精品一区二区三区在线播放| 91精品国产一区二区三区| 欧美日韩电影在线| 欧美一级国产精品| 日韩欧美国产高清| 久久综合九色综合97婷婷女人 | 国产精品久久久久久久久免费丝袜 | 精品中文字幕一区二区| 国模少妇一区二区三区| 国产精品亚洲午夜一区二区三区| 丁香网亚洲国际| 成人av在线网站| 色域天天综合网| 欧美中文字幕一区二区三区亚洲 | 中文字幕一区二区三区不卡在线| 国产精品高潮久久久久无| 一区二区三区四区精品在线视频| 一区二区欧美国产| 日韩激情视频在线观看| 韩国三级中文字幕hd久久精品| 国产精品一区免费视频| 成人理论电影网| 欧美主播一区二区三区美女| 91麻豆精品国产| 欧美激情在线观看视频免费| 国产精品成人免费精品自在线观看| 亚洲视频综合在线| 日本欧美肥老太交大片| 国产精品一区三区| 色综合 综合色| 精品久久久久一区| ●精品国产综合乱码久久久久| 亚洲国产欧美日韩另类综合| 国产制服丝袜一区| 色婷婷综合久色| 欧美电影免费观看高清完整版在线 | 国产精品1024| 欧美色欧美亚洲另类二区| 精品国产自在久精品国产| 中文字幕一区二区三区av| 日产国产欧美视频一区精品| 国产91精品欧美| 91精品一区二区三区久久久久久| 国产视频一区二区在线| 亚洲国产成人精品视频| 国产精品99久久久久久似苏梦涵| 欧美三区在线视频| 国产精品久久久久久久裸模| 另类欧美日韩国产在线| 色婷婷国产精品综合在线观看| 精品盗摄一区二区三区| 亚洲成av人综合在线观看| 东方欧美亚洲色图在线| 日韩美一区二区三区| 亚洲一区二区三区精品在线| 国产成a人亚洲精| 欧美一区二区三区视频| 亚洲综合精品自拍| 91丨九色丨蝌蚪丨老版| 久久欧美中文字幕| 蜜臀精品久久久久久蜜臀| 在线中文字幕不卡| 国产精品久久久久久久久免费相片| 久久国产三级精品| 91精品国产一区二区三区蜜臀| 亚洲精品va在线观看| 成人福利电影精品一区二区在线观看| 91精品国产综合久久精品app| 亚洲伦理在线免费看| 成人动漫一区二区三区| 国产亚洲欧美在线| 黄页视频在线91| 日韩亚洲欧美一区| 日本 国产 欧美色综合| 欧美一级二级三级乱码| 日韩二区三区四区| 日韩欧美国产精品| 国产一区二区0| 26uuu亚洲| 国产精品18久久久久久vr| 欧美国产成人精品| 91在线国内视频| 亚洲激情图片一区| 欧亚一区二区三区| 热久久一区二区| 精品国产一二三区| 成人97人人超碰人人99|