久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

圖編輯系統(tǒng)設(shè)計(jì)指南:從數(shù)據(jù)模型到布局與性能的工程實(shí)踐

圖編輯系統(tǒng)設(shè)計(jì)指南:從數(shù)據(jù)模型到布局與性能的工程實(shí)踐 1. 為什么我會(huì)開始認(rèn)真思考 diagram-design 這件事先坦白一個(gè)背景我做的很多項(xiàng)目都需要畫圖——架構(gòu)圖、流程圖、時(shí)序圖、拓?fù)鋱D、ER 圖不一而足。早年沒(méi)太把這件事當(dāng)回事腦子里有個(gè)大概就開始堆代碼今天用某個(gè)在線工具拖一拖明天用另外一款軟件補(bǔ)一補(bǔ)后天發(fā)現(xiàn)某個(gè)模塊邏輯盤不清干脆 PPT 畫個(gè)示意就丟給下游。結(jié)果就是圖與圖之間風(fēng)格混亂、坐標(biāo)系不統(tǒng)一、數(shù)據(jù)模型對(duì)不上一個(gè)圖換一個(gè)人維護(hù)就徹底沒(méi)法看了。后來(lái)做了一個(gè)以“圖”為核心的跨平臺(tái)系統(tǒng)才真正把 diagram design 當(dāng)作一個(gè)嚴(yán)肅工程問(wèn)題來(lái)看待。diagram-design 這個(gè)標(biāo)題表面看是“圖表設(shè)計(jì)”但做過(guò)的朋友應(yīng)該都能感受得到真正難的從來(lái)不是“畫圖”這個(gè)動(dòng)作而是怎么把業(yè)務(wù)結(jié)構(gòu)拆解成節(jié)點(diǎn)、邊、分組、布局和交互這套模型再在這套模型之上做出可擴(kuò)展、可維護(hù)、性能還過(guò)得去的渲染方案。畫一個(gè)靜態(tài)圖誰(shuí)都會(huì)畫一套可以編輯、自動(dòng)布局、實(shí)時(shí)聯(lián)動(dòng)、支持大數(shù)據(jù)量的圖形系統(tǒng)那就是另一回事了。這篇內(nèi)容適合誰(shuí)如果你正在做可視化編輯器、流程圖引擎、拓?fù)鋱D平臺(tái)、數(shù)據(jù)血緣圖或者只是被“項(xiàng)目里上百個(gè)圖形節(jié)點(diǎn)怎么管理”這件事折磨這篇文章應(yīng)該能提供一個(gè)從我有思路到落到工程實(shí)現(xiàn)的完整剖面。我會(huì)聊技術(shù)選型、數(shù)據(jù)建模、布局算法、交互與渲染的取舍也會(huì)把我在實(shí)際項(xiàng)目里踩過(guò)的一些坑直接攤開來(lái)講。不會(huì)有太多玄學(xué)盡量每一個(gè)結(jié)論都能對(duì)應(yīng)到實(shí)際代碼和真實(shí)場(chǎng)景。2. 先用一張“圖”拆解 diagram-design 的問(wèn)題域很多人拿到“做一個(gè)圖表設(shè)計(jì)系統(tǒng)”的需求第一反應(yīng)是去找渲染庫(kù)這是順序錯(cuò)了。渲染是整個(gè)鏈路里最末端的東西前面還有數(shù)據(jù)模型、布局邏輯和交互協(xié)議。如果這三層不先想明白哪怕選了再?gòu)?qiáng)的渲染引擎后面也會(huì)被各種臨時(shí)需求扯得七零八落。2.1 圖的本質(zhì)節(jié)點(diǎn)、邊、端口、分組與畫布把任意一張圖拆到底核心元素就這兩類節(jié)點(diǎn)和邊。但真實(shí)業(yè)務(wù)里光有這兩類遠(yuǎn)遠(yuǎn)不夠。以流程圖為例節(jié)點(diǎn)可能是“開始”“結(jié)束”“處理步驟”“判斷分支”邊是帶方向的箭頭但判斷分支的邊上得帶標(biāo)簽比如“是”和“否”。以網(wǎng)絡(luò)拓?fù)鋱D為例節(jié)點(diǎn)是服務(wù)器和交換機(jī)邊是鏈路但鏈路上可能有多條虛擬連接連線的語(yǔ)義遠(yuǎn)比箭頭復(fù)雜。以 ER 圖為例節(jié)點(diǎn)是實(shí)體表邊是關(guān)系但關(guān)系有一對(duì)多、多對(duì)多之分邊上還需要標(biāo)注主外鍵字段。所以在設(shè)計(jì)數(shù)據(jù)模型的時(shí)候我建議一開始就把這幾類基礎(chǔ)設(shè)施建好節(jié)點(diǎn)Node坐標(biāo)、尺寸、類型、樣式、業(yè)務(wù)數(shù)據(jù)掛載點(diǎn)。端口Port節(jié)點(diǎn)上用于連線的錨點(diǎn)決定連線從哪個(gè)位置引出。邊Edge源端口與目標(biāo)端口、路徑點(diǎn)、箭頭樣式、線型、標(biāo)簽。分組Group用于表達(dá)容器關(guān)系比如泳道、子圖、分組框。畫布Canvas全局變換信息、縮放比例、可視區(qū)域、網(wǎng)格設(shè)置。如果項(xiàng)目里一開始就接受“邊只連接節(jié)點(diǎn)、不連接端口”這種簡(jiǎn)化模型后面做節(jié)點(diǎn)拖動(dòng)、邊跟隨、錨點(diǎn)吸附時(shí)會(huì)付出大量返工成本。我的經(jīng)驗(yàn)是寧可第一版把端口模型做上去哪怕界面層暫時(shí)隱藏端口也比后續(xù)硬塞進(jìn)一個(gè)不支持的模型要省力得多。2.2 從“畫一張圖”到“圖系統(tǒng)”跨度在哪里“畫一張圖”是單次行為畫完就結(jié)束信息不流動(dòng)。而圖系統(tǒng)要考慮的是持續(xù)的編輯、序列化、數(shù)據(jù)驅(qū)動(dòng)更新、多人協(xié)作甚至版本管理。這里有一個(gè)容易被低估的復(fù)雜度來(lái)源圖的序列化格式。如果只是想畫個(gè)靜態(tài)效果把節(jié)點(diǎn)坐標(biāo)和邊路徑直接寫進(jìn) JSON 就夠了??梢坏┮胱詣?dòng)布局坐標(biāo)就成了派生數(shù)據(jù)而不是源數(shù)據(jù)——你存的是圖的拓?fù)浣Y(jié)構(gòu)坐標(biāo)是布局引擎算出來(lái)的。這時(shí)候若還把坐標(biāo)當(dāng)成第一公民寫死自動(dòng)布局和手動(dòng)調(diào)整之間就會(huì)天天打架。我后來(lái)采用的方案是源數(shù)據(jù)只保存節(jié)點(diǎn)、邊、端口的連接關(guān)系和業(yè)務(wù)字段坐標(biāo)則作為一個(gè)可選的“用戶覆蓋層”保存。布局引擎產(chǎn)出的坐標(biāo)寫入覆蓋層手動(dòng)微調(diào)也寫入覆蓋層而拓?fù)浔旧硎冀K是干凈的結(jié)構(gòu)化數(shù)據(jù)。這套設(shè)計(jì)的直接收益是后續(xù)加新布局算法、做子圖復(fù)用、做圖形模板都不需要?jiǎng)痈?. 技術(shù)選型的底層邏輯老牌庫(kù)就一定省心嗎圖表領(lǐng)域可選的技術(shù)棧其實(shí)不多但每個(gè)方案都各有各的脾氣。我把主流路線梳理了一遍重點(diǎn)不是“誰(shuí)最強(qiáng)”而是“誰(shuí)更適合作為自研圖系統(tǒng)的基礎(chǔ)”。3.1 三條主流路線的對(duì)比市面上做 diagram 相關(guān)工具底層渲染路線大抵分三類一是基于 SVG 的方案。代表庫(kù)包括老牌的 Raphael 和后來(lái)的一些封裝庫(kù)。SVG 的優(yōu)點(diǎn)在于 DOM 集成度高事件處理天然樣式可以用 CSS 控制做小型和中型圖非常順手。缺點(diǎn)是節(jié)點(diǎn)數(shù)量一旦上千DOM 節(jié)點(diǎn)數(shù)量會(huì)成為明顯的性能瓶頸拖拽縮放時(shí)也會(huì)感覺(jué)跟手度不夠。二是基于 Canvas 的方案。一次繪制、整體渲染性能上限比 SVG 高很多適合節(jié)點(diǎn)數(shù)多、交互相對(duì)簡(jiǎn)單的場(chǎng)景比如純展示類拓?fù)?。缺點(diǎn)是事件命中檢測(cè)要自己做文字換行、樣式定制都得模擬一套 UI 體系開發(fā)成本明顯上去了。三是基于 WebGL 的方案。這是真正的重型武器性能天花板最高能做海量節(jié)點(diǎn)和復(fù)雜動(dòng)效但開發(fā)門檻也最高普通圖系統(tǒng)上屬于殺雞用牛刀。如果項(xiàng)目里沒(méi)有“幾萬(wàn)個(gè)節(jié)點(diǎn)還要流暢漫游”這類極端需求建議不要一上來(lái)就碰。3.2 我最終確定的自研組合開頭提到的那個(gè)跨平臺(tái)系統(tǒng)節(jié)點(diǎn)規(guī)模常規(guī)在幾百到幾千這個(gè)區(qū)間同時(shí)要求支持用戶交互編輯、拖拽、縮放、框選還要能導(dǎo)入導(dǎo)出多種格式。我最后選的技術(shù)組合是基于 SVG 自研核心渲染引擎配合虛擬化渲染思路來(lái)做性能兜底。一句話總結(jié)就是先選對(duì)工具車再考慮給車上裝什么樣的引擎。為什么不是 Canvas因?yàn)樵诰庉嬓蛨D系統(tǒng)里“精細(xì)到每個(gè)節(jié)點(diǎn)、每條邊的交互”是核心訴求。SVG 天然就有獨(dú)立 DOM 節(jié)點(diǎn)來(lái)做事件綁定框選、拖拽、命中檢測(cè)這些都順手很多。Canvas 要自己實(shí)現(xiàn)的交互層工作量幾乎是 SVG 方案的兩三倍。為什么不是直接套某個(gè)大而全的現(xiàn)成庫(kù)因?yàn)檫@個(gè)項(xiàng)目需要深度定制自定義節(jié)點(diǎn)形狀、自定義端口規(guī)則、自定義自動(dòng)布局算法、特定的數(shù)據(jù)格式對(duì)接。成熟商業(yè)庫(kù)的封裝層再厚到了這一步也會(huì)成為障礙。與其花大力氣繞開別人的封裝不如在底層之上只保留少量惰性封裝。補(bǔ)充一個(gè)表方便你看對(duì)比方案交互開發(fā)成本性能上限定制自由度適合場(chǎng)景純 SVG 自研低中配合優(yōu)化手段可提升高中量級(jí)編輯型圖系統(tǒng)Canvas 自研高高高展示型、超大量節(jié)點(diǎn)現(xiàn)成 Vue/React 圖庫(kù)低中低快速交付、標(biāo)準(zhǔn)圖型WebGL 自研很高極高很高極端大規(guī)模場(chǎng)景這套選型落地的過(guò)程中我也有一些心得不要追求“一步到位的全能力框架”先做一個(gè)只支持有限節(jié)點(diǎn)類型、有限交互的版本跑通鏈路再逐步開放能力。圖表系統(tǒng)的復(fù)雜度是螺旋上升的最怕一開始就引入大量抽象概念結(jié)果自己先被抽象困住了。4. 數(shù)據(jù)模型先行如何把業(yè)務(wù)“翻譯”成圖結(jié)構(gòu)選定技術(shù)棧之后我做的第一件事不是畫界面而是定數(shù)據(jù)模型。這個(gè)階段多花一周后面少花一個(gè)月。4.1 核心實(shí)體的最小字段集我把最初的 TypeScript 類型定義精簡(jiǎn)成下面這個(gè)層次這是整個(gè)系統(tǒng)最關(guān)鍵的代碼片段沒(méi)有之一interface DiagramNode { id: string; type: string; // 節(jié)點(diǎn)類型如 process, start, end x: number; y: number; width: number; height: number; ports: Port[]; // 端口列表 data: Recordstring, any; // 業(yè)務(wù)數(shù)據(jù)掛載點(diǎn) groupId?: string; // 所屬分組 } interface Port { id: string; nodeId: string; side: top | right | bottom | left; // 所在方位 index?: number; // 同一側(cè)多個(gè)端口時(shí)的順序 } interface Edge { id: string; source: PortRef; // { nodeId, portId } target: PortRef; points?: Point[]; // 經(jīng)過(guò)的關(guān)鍵路徑點(diǎn) label?: string; style?: EdgeStyle; }這里有兩個(gè)容易被忽視的設(shè)計(jì)點(diǎn)第一個(gè)是Port獨(dú)立成實(shí)體。連線不是“從這個(gè)節(jié)點(diǎn)中心到那個(gè)節(jié)點(diǎn)中心”而是“從某節(jié)點(diǎn)的一個(gè)端口到另一節(jié)點(diǎn)的一個(gè)端口”。在這個(gè)模型下節(jié)點(diǎn)拖走時(shí)邊的端點(diǎn)能自動(dòng)跟隨到正確位置多端口節(jié)點(diǎn)也能區(qū)分“這根線究竟連哪個(gè)插孔”。第二個(gè)是節(jié)點(diǎn)的data字段它專門用來(lái)掛載業(yè)務(wù)數(shù)據(jù)。圖系統(tǒng)本身不關(guān)心業(yè)務(wù)字段是啥但交互層、校驗(yàn)層、后端同步層都需要一個(gè)統(tǒng)一入口來(lái)讀寫。把業(yè)務(wù)數(shù)據(jù)和圖形數(shù)據(jù)混在一個(gè)平級(jí)字段里短期省事長(zhǎng)期必亂。4.2 序列化格式的版本兼容設(shè)計(jì)圖數(shù)據(jù)一定會(huì)經(jīng)歷版本迭代。今天你的圖里有節(jié)點(diǎn)、邊、端口明天可能就要加“子圖”或者“泳道”后天可能又要加“聚合節(jié)點(diǎn)”。如果在序列化結(jié)構(gòu)里不做版本字段和兼容策略老數(shù)據(jù)怎么遷移將成為一個(gè)大麻煩。我用的做法是給所有持久化數(shù)據(jù)加一個(gè)schemaVersion字段同時(shí)維護(hù)一個(gè)遷移函數(shù)鏈。每次數(shù)據(jù)結(jié)構(gòu)變化就新增一個(gè)遷移函數(shù)而不是直接改舊數(shù)據(jù)的讀取邏輯。加載時(shí)如果發(fā)現(xiàn)版本號(hào)低于當(dāng)前版本就依次執(zhí)行遷移函數(shù)把舊數(shù)據(jù)升級(jí)到最新格式。這套思路其實(shí)就是軟件工程里的數(shù)據(jù)庫(kù)遷移思路搬到前端圖數(shù)據(jù)上一樣適用。具體遷移函數(shù)示例const migrations: Recordnumber, (oldData: any) any { 1: (data) { // 版本1升級(jí)到版本2為每個(gè)節(jié)點(diǎn)補(bǔ)充空數(shù)組 ports return { ...data, nodes: data.nodes.map((n: any) ({ ...n, ports: [], groupId: undefined })) }; }, 2: (data) { // 版本2升級(jí)到版本3edge 從 node 引用改為 port 引用 return { ...data, edges: data.edges.map((e: any) ({ ...e, source: { nodeId: e.source, portId: e.sourcePort }, target: { nodeId: e.target, portId: e.targetPort } })) }; } }; function upgrade(data: any): any { let current data; while (current.schemaVersion LATEST_VERSION) { const next current.schemaVersion 1; current migrations[next](current); current.schemaVersion next; } return current; }如果沒(méi)有這套機(jī)制第一版上線后一改數(shù)據(jù)格式用戶手里的圖就打不開了那是災(zāi)難級(jí)事故。我現(xiàn)在對(duì)這個(gè)事情敏感度很高凡是能持久化的結(jié)構(gòu)必須有版本標(biāo)識(shí)、必須有遷移路徑、必須有新舊兼容的至少一個(gè)迭代容錯(cuò)周期。4.3 業(yè)務(wù)語(yǔ)義與視覺(jué)表達(dá)的邊界圖系統(tǒng)里最容易出問(wèn)題的地方是把視覺(jué)表達(dá)直接當(dāng)成業(yè)務(wù)語(yǔ)義存儲(chǔ)。比如說(shuō)某個(gè)節(jié)點(diǎn)在業(yè)務(wù)上屬于“已下線”狀態(tài)你可能會(huì)想給它渲染成灰色然后在數(shù)據(jù)模型里也記一個(gè)color: gray。短期看著沒(méi)問(wèn)題可一旦業(yè)務(wù)規(guī)則變成“已下線”要顯示成紅色你就得去改全量數(shù)據(jù)而不是只改一套配置。我的做法是數(shù)據(jù)模型里存穩(wěn)定的業(yè)務(wù)狀態(tài)字段比如status: online | offline視覺(jué)層統(tǒng)一維護(hù)一份“狀態(tài)到樣式的映射表”。當(dāng)多個(gè)節(jié)點(diǎn)共用同一種視覺(jué)規(guī)則時(shí)把樣式注冊(cè)成可復(fù)用的主題規(guī)則而不是散布在各節(jié)點(diǎn)數(shù)據(jù)里。用一句話概括就是數(shù)據(jù)存事實(shí)樣式存映射規(guī)則集中在主題層。這個(gè)原則同樣適用于邊的類型。業(yè)務(wù)里的“依賴關(guān)系”和“調(diào)用關(guān)系”在圖上可能只是顏色和線型不同但在數(shù)據(jù)模型里必須是兩個(gè)不同的edgeType。如果只依賴顏色區(qū)分后續(xù)做數(shù)據(jù)導(dǎo)出、權(quán)限控制、語(yǔ)義分析的時(shí)候就會(huì)缺失關(guān)鍵信息。5. 自動(dòng)布局決定圖表可讀性的隱藏引擎如果說(shuō)數(shù)據(jù)模型是圖系統(tǒng)的骨架那自動(dòng)布局就是它的神經(jīng)系統(tǒng)。理想的布局算法能把一團(tuán)亂麻的拓?fù)渥詣?dòng)整理成人類閱讀時(shí)覺(jué)得“順眼”的結(jié)構(gòu)。順眼是個(gè)主觀感受但底層規(guī)律其實(shí)非常穩(wěn)定減少交叉邊、保持層級(jí)方向一致、同類節(jié)點(diǎn)對(duì)齊、連線盡量短。5.1 分層布局、力導(dǎo)向布局和正交布局的應(yīng)用邊界目前開源的布局算法核心就那幾類選錯(cuò)了應(yīng)用場(chǎng)景體驗(yàn)會(huì)斷崖式下跌。分層布局的核心思路是先對(duì)圖做拓?fù)渑判虬压?jié)點(diǎn)按層級(jí)排開再在每一層內(nèi)部調(diào)整順序以降低邊交叉。流程圖、狀態(tài)機(jī)、依賴關(guān)系圖都適合分層布局因?yàn)樗烊挥小皬纳贤?、從左往右”的閱讀方向感。實(shí)際項(xiàng)目里大多數(shù)業(yè)務(wù)圖的默認(rèn)布局我都會(huì)優(yōu)先考慮分層布局。力導(dǎo)向布局模擬的是物理模型節(jié)點(diǎn)之間互相排斥、邊就像彈簧互相拉引迭代若干次后達(dá)到穩(wěn)定狀態(tài)。這種布局適合沒(méi)有明確方向感的圖比如社交網(wǎng)絡(luò)關(guān)系、系統(tǒng)模塊親密度圖。優(yōu)點(diǎn)是不需要對(duì)圖做任何結(jié)構(gòu)假設(shè)缺點(diǎn)是結(jié)果帶有隨機(jī)性同一個(gè)圖布局兩遍節(jié)點(diǎn)位置可能完全不一樣。對(duì)經(jīng)常需要“復(fù)現(xiàn)同樣視覺(jué)效果”的場(chǎng)景這是個(gè)大忌。正交布局則更貼近電路圖和建筑平面圖的風(fēng)格所有線段都走水平或垂直方向折彎處用直角。ER 圖、微服務(wù)調(diào)用鏈這種強(qiáng)調(diào)連線清晰度的場(chǎng)景正交布局非常有用不過(guò)代價(jià)是路徑計(jì)算的復(fù)雜度明顯更高。實(shí)際項(xiàng)目中我一般這樣分配有天然層級(jí)關(guān)系的用分層布局不分層但強(qiáng)調(diào)聚類關(guān)系的用力導(dǎo)向需要嚴(yán)謹(jǐn)連線的圖允許用戶在自動(dòng)布局之后手動(dòng)微調(diào)路徑點(diǎn)而不是強(qiáng)行全自動(dòng)。5.2 我基于 dagre 的二次封裝與定制業(yè)界做分層布局dagre 是個(gè)繞不開的庫(kù)。它實(shí)現(xiàn)的是經(jīng)典的 Sugiyama 分層算法框架輸入一個(gè)圖結(jié)構(gòu)輸出帶坐標(biāo)的布局結(jié)果。但直接用 dagre 做業(yè)務(wù)系統(tǒng)還是有幾個(gè)很別扭的地方。第一個(gè)問(wèn)題dagre 不知道你的節(jié)點(diǎn)尺寸它默認(rèn)把節(jié)點(diǎn)當(dāng)成等寬高的矩形。真實(shí)場(chǎng)景中節(jié)點(diǎn)寬度差異很大有的節(jié)點(diǎn)要放圖標(biāo)有的節(jié)點(diǎn)是一大段文本。所以我在封裝時(shí)做了一步“先按默認(rèn)尺寸布局再按實(shí)際尺寸調(diào)整層級(jí)內(nèi)對(duì)齊”大致思路如下function layeredLayout(graph: GraphModel, options: LayoutOptions) { // 第一遍預(yù)估尺寸跑 dagre 拿到相對(duì)層級(jí)與順序 const preliminary dagre.graphlib.Graph(); preliminary.setGraph({ rankdir: options.rankdir }); graph.nodes.forEach(node { preliminary.setNode(node.id, { width: node.width || DEFAULT_WIDTH, height: node.height || DEFAULT_HEIGHT }); }); graph.edges.forEach(edge { preliminary.setEdge(edge.source.nodeId, edge.target.nodeId); }); dagre.layout(preliminary); // 第二遍按實(shí)際尺寸做層內(nèi)對(duì)齊兼顧同一層節(jié)點(diǎn)的中心線對(duì)齊 const layers groupByRank(preliminary, graph); const result: Recordstring, { x: number; y: number } {}; layers.forEach((layer, layerIndex) { const maxHeight Math.max(...layer.map(n graph.node(n).height)); layer.forEach((nodeId, index) { const node graph.node(nodeId); result[nodeId] { x: layerOffset(nodeId, index, layers), y: layerIndex * (maxHeight options.levelGap) }; }); }); return result; }第二個(gè)問(wèn)題dagre 輸出的布局沒(méi)有考慮端口方位。它默認(rèn)邊從節(jié)點(diǎn)中心連到節(jié)點(diǎn)中心可真實(shí)圖上連線應(yīng)該有明確的出口和入口方向。我的做法是在布局階段先以節(jié)點(diǎn)中心坐標(biāo)做整體排布排完后再根據(jù)邊的相對(duì)方位自動(dòng)推導(dǎo)端口方向這樣既保留了 dagre 的整體結(jié)構(gòu)穩(wěn)定性又讓局部的連線看起來(lái)更自然。第三個(gè)讓我折騰了一陣的問(wèn)題節(jié)點(diǎn)寬度差異導(dǎo)致同層節(jié)點(diǎn)參差不齊。比如同一層的三個(gè)節(jié)點(diǎn)一個(gè) 300px 寬兩個(gè) 120px 寬如果只是簡(jiǎn)單地把它們擠在一行大節(jié)點(diǎn)會(huì)頂著左右兩邊小節(jié)點(diǎn)周圍留出大片空白。最終我采用“層內(nèi)網(wǎng)格居中”策略把每層寬度統(tǒng)一拉伸到該層最大節(jié)點(diǎn)的寬度小節(jié)點(diǎn)在該列內(nèi)水平居中。視覺(jué)效果會(huì)整齊很多。5.3 布局重計(jì)算的觸發(fā)策略布局算法有個(gè)常見(jiàn)的性能陷阱用戶只是拖動(dòng)了某一個(gè)節(jié)點(diǎn)整個(gè)圖都重新布局了一遍。這會(huì)讓用戶感覺(jué)到“圖不聽話”因?yàn)榉潜煌蟿?dòng)的節(jié)點(diǎn)也亂跳了。我調(diào)參后的觸發(fā)策略是節(jié)點(diǎn)拖動(dòng)過(guò)程中只更新被拖動(dòng)節(jié)點(diǎn)及其直接相連邊的路徑不做全局重排。節(jié)點(diǎn)拖動(dòng)結(jié)束標(biāo)記該節(jié)點(diǎn)坐標(biāo)為用戶覆蓋后續(xù)自動(dòng)布局跳過(guò)它。手動(dòng)觸發(fā)自動(dòng)布局比如點(diǎn)擊“重新布局”按鈕執(zhí)行全圖重排此時(shí)清除所有手動(dòng)覆蓋信息。圖結(jié)構(gòu)變化新增/刪除節(jié)點(diǎn)、邊以增量方式打補(bǔ)丁優(yōu)先保持已有節(jié)點(diǎn)位置不變讓新節(jié)點(diǎn)在旁邊“長(zhǎng)出來(lái)”只有在結(jié)構(gòu)變化比例過(guò)大時(shí)才主動(dòng)做全量重排。這套策略的核心思想是自動(dòng)布局要尊重用戶的每一次手動(dòng)調(diào)整只有在用戶明確要求時(shí)才能大動(dòng)干戈。否則光是一個(gè)“拖完節(jié)點(diǎn)又彈回去”的問(wèn)題就能把用戶逼瘋。6. 交互與渲染的細(xì)節(jié)工程拖拽、縮放與路徑重算圖和普通 UI 組件最大的不同在于它面對(duì)的是一塊無(wú)邊際的虛擬畫布。所有交互計(jì)算都要在圖坐標(biāo)和屏幕坐標(biāo)之間做轉(zhuǎn)換這就是整個(gè)交互層的數(shù)學(xué)地基。6.1 坐標(biāo)變換與縮放系數(shù)管理假設(shè)畫布有一個(gè)全局變換縮放系數(shù)scale平移偏移量tx、ty。那么屏幕坐標(biāo)和邏輯坐標(biāo)之間的換算關(guān)系就是screenX logicX * scale tx screenY logicY * scale ty反推邏輯坐標(biāo)logicX (screenX - tx) / scale logicY (screenY - ty) / scale這套公式本身不復(fù)雜但工程上有幾個(gè)細(xì)節(jié)容易出問(wèn)題。第一個(gè)是鼠標(biāo)滾輪縮放的中心點(diǎn)。如果鼠標(biāo)停在畫布某處滾輪縮放之后鼠標(biāo)下的那個(gè)邏輯坐標(biāo)點(diǎn)應(yīng)該在屏幕位置保持不變。很多初版實(shí)現(xiàn)都沒(méi)做這個(gè)校正結(jié)果就是縮放時(shí)圖總是往左上角縮或者上下左右亂飄。校正公式是把光標(biāo)處的邏輯坐標(biāo)作為錨點(diǎn)先換算縮放前后的偏移量差再補(bǔ)償?shù)絫x、ty上。第二個(gè)是編輯狀態(tài)下的坐標(biāo)精度。當(dāng)縮放系數(shù)特別大比如放大到 200%同一個(gè)邏輯坐標(biāo)在不同幀之間小數(shù)位抖動(dòng)會(huì)導(dǎo)致節(jié)點(diǎn)邊緣不停閃爍。我的做法是渲染層統(tǒng)一用整數(shù)化的邏輯坐標(biāo)避免累積誤差。6.2 連線路徑的自動(dòng)規(guī)避與折線計(jì)算邊是圖系統(tǒng)中最“難畫”的元素因?yàn)樗穆窂近c(diǎn)需要繞過(guò)節(jié)點(diǎn)還需要在方向變化處畫成直角折線。直角折線計(jì)算的標(biāo)準(zhǔn)思路是如果源端口和目標(biāo)端口在同一水平線就走一段水平線如果不在就要先出端口方向一段“引出線”再走正交線段連接。我用的是簡(jiǎn)化版 A* 尋路算法作用范圍限制在包圍盒所在的局部區(qū)域。具體來(lái)說(shuō)網(wǎng)格化源節(jié)點(diǎn)到目標(biāo)節(jié)點(diǎn)之間的矩形區(qū)域把其他節(jié)點(diǎn)當(dāng)成障礙物搜索一條從源端口到目標(biāo)端口的最短正交路徑。這個(gè)算法對(duì)少數(shù)連線場(chǎng)景表現(xiàn)很好但連線一旦密集比如上百條每根線都做獨(dú)立尋路會(huì)產(chǎn)生大量重疊和交叉這也是正交布局在復(fù)雜場(chǎng)景下比較難解決的問(wèn)題。我采取的妥協(xié)方案是自動(dòng)計(jì)算完路徑后再做一次基于熵的路徑平滑把共線的線路合并交叉情況用曲線過(guò)渡簡(jiǎn)化視覺(jué)噪聲。效果上自動(dòng)連線的“粗糙感”會(huì)明顯減輕雖然沒(méi)法做到完全零交叉但在千級(jí)節(jié)點(diǎn)規(guī)模的系統(tǒng)里已經(jīng)夠用。6.3 選中的反饋與編輯器的撤銷/重做圖編輯器里用戶對(duì)“選中”的反饋非常敏感。節(jié)點(diǎn)選中時(shí)會(huì)出現(xiàn)選中框邊選中時(shí)會(huì)出現(xiàn)路徑錨點(diǎn)同一時(shí)間可以框選多個(gè)對(duì)象。這個(gè)交互層其實(shí)藏著一個(gè)大坑撤銷/重做棧。圖編輯的撤銷和文本編輯的撤銷復(fù)雜度完全不在一個(gè)量級(jí)。光是把一個(gè)節(jié)點(diǎn)從 A 點(diǎn)拖到 B 點(diǎn)中間會(huì)經(jīng)過(guò)幾十次鼠標(biāo)移動(dòng)事件如果不做合并撤銷棧會(huì)被幾十條“位置微調(diào)”記錄撐爆用戶按一次撤銷只能回退 1 像素體驗(yàn)極其糟糕。我后來(lái)實(shí)現(xiàn)的是“命令模式 操作批次合并”連續(xù)同類型的變更比如連續(xù)拖拽、連續(xù)縮放、連續(xù)框選移動(dòng)合并成一個(gè)撤銷記錄每次交互結(jié)束后才 push 進(jìn)撤銷棧。像這樣class CommandStack { private stack: Command[] []; private batch: Command[] | null null; beginBatch() { this.batch []; } push(command: Command) { if (this.batch) { this.batch.push(command); } else { this.stack.push(command); } } endBatch() { if (this.batch this.batch.length 0) { this.stack.push(this.batch); } this.batch null; } undo() { const cmd this.stack.pop(); if (Array.isArray(cmd)) { cmd.reverse().forEach(c c.undo()); } else if (cmd) { cmd.undo(); } } }每次鼠標(biāo)按下時(shí)beginBatch()鼠標(biāo)松開時(shí)endBatch()整個(gè)拖拽過(guò)程只留下一個(gè)可撤銷步驟用戶按 CtrlZ 時(shí)能夠一次回到拖拽前狀態(tài)。這個(gè)設(shè)計(jì)雖然代碼行數(shù)不多但對(duì)編輯類工具的使用體驗(yàn)提升是立竿見(jiàn)影的。7. 性能優(yōu)化的實(shí)戰(zhàn)路徑當(dāng)棱角開始穿透 SVG 的天花板SVG 的上限在幾千個(gè)節(jié)點(diǎn)時(shí)就會(huì)開始顯形這個(gè)數(shù)字聽起來(lái)好像很夠用可真到了流程圖編輯場(chǎng)景一個(gè)主節(jié)點(diǎn)掛幾十個(gè)子節(jié)點(diǎn)再疊加編輯緩存和歷史記錄內(nèi)存占用很快會(huì)飆升。我經(jīng)歷過(guò)的性能拐點(diǎn)很明確節(jié)點(diǎn)數(shù)上到 2000 左右拖拽開始卡5000 左右直接沒(méi)法互動(dòng)。所以性能優(yōu)化不是可選項(xiàng)是必選項(xiàng)。7.1 可視區(qū)裁剪是第一優(yōu)先級(jí)的優(yōu)化圖表畫布是個(gè)無(wú)邊際的世界但用戶眼睛能看到的區(qū)域其實(shí)很小。不做可視區(qū)裁剪等于把整個(gè)城市的地圖一次性畫出來(lái)而用戶只盯著一個(gè)街區(qū)。實(shí)現(xiàn)思路是維護(hù)一個(gè)可視矩形viewBounds遍歷節(jié)點(diǎn)時(shí)只渲染與viewBounds有交集的節(jié)點(diǎn)對(duì)完全在可視區(qū)外的節(jié)點(diǎn)直接跳過(guò) DOM 創(chuàng)建。邊的渲染判斷稍微復(fù)雜一些因?yàn)橐粭l邊的兩個(gè)端點(diǎn)可能都在可視區(qū)外但路徑中途穿過(guò)可視區(qū)。所以邊不能用“兩端是否在可視區(qū)”來(lái)判斷需要判斷折線線段與viewBounds是否相交。7.2 分層渲染靜態(tài)層與交互層分離很多圖表卡頓的根源在于靜態(tài)展示的圖形和用戶正在拖拽的節(jié)點(diǎn)混在同一個(gè)渲染層級(jí)每次交互都導(dǎo)致全量重繪。我采用的方案是分層底層靜態(tài)背景網(wǎng)格線、大節(jié)點(diǎn)、固定樣式元素只在畫布變換結(jié)束或數(shù)據(jù)變更時(shí)重繪。中間層動(dòng)態(tài)內(nèi)容節(jié)點(diǎn)和邊的渲染主體在拖拽、縮放時(shí)按需更新。頂層交互反饋層選中框、拖拽中的預(yù)覽路徑、臨時(shí)高亮每幀刷新但元素?cái)?shù)量極少。TS 項(xiàng)目里對(duì)應(yīng)實(shí)現(xiàn)就是疊加多個(gè)g組操作時(shí)精準(zhǔn)定位到對(duì)應(yīng)層級(jí)的g而不是每次都重建整個(gè)畫布。7.3 批量更新原則與渲染節(jié)流節(jié)點(diǎn)數(shù)據(jù)變化是高頻事件如果每次變化都立即操作對(duì)應(yīng) DOM往往會(huì)造成無(wú)謂的性能開銷。我多做了一個(gè)隊(duì)列化更新機(jī)制把一批變化統(tǒng)一收集放到 requestAnimationFrame 的回調(diào)里一次處理。這樣在同一次交互內(nèi)的幾十次節(jié)點(diǎn)移動(dòng)最終只觸發(fā)一次批量更新。類似的節(jié)流還用在了縮放事件上。滾輪事件在瀏覽器里頻率非常高如果每幀都去重算所有邊的路徑必然卡頓。我的做法是縮放過(guò)程中只更新畫布的 transform 和網(wǎng)格線等縮放停止約 150ms 無(wú)新事件后才重算邊上路徑點(diǎn)的寬度。視覺(jué)上無(wú)感性能上會(huì)有質(zhì)的提升。8. 一路摸爬滾打總結(jié)的 diagram-design 實(shí)用準(zhǔn)則最后把這段經(jīng)歷里最有復(fù)用價(jià)值的東西濃縮成幾條原則這些是我每次做圖系統(tǒng)時(shí)都會(huì)默念的清單。先定數(shù)據(jù)模型再選渲染庫(kù)。數(shù)據(jù)模型一旦定錯(cuò)后續(xù)所有代碼都在給錯(cuò)誤模型打補(bǔ)丁。節(jié)點(diǎn)、端口、邊、分組、畫布這五個(gè)實(shí)體齊全了再去接渲染層、布局算法和交互邏輯。自動(dòng)布局和用戶手動(dòng)調(diào)整的關(guān)系要趁早想清楚。我用“用戶覆蓋優(yōu)先、自動(dòng)布局尊重覆蓋、用戶主動(dòng)觸發(fā)才全量重排”這套策略極大避免了布局和手動(dòng)的沖突。如果沒(méi)有這條策略圖系統(tǒng)會(huì)處于一種“永遠(yuǎn)在跟用戶搶奪控制權(quán)”的狀態(tài)非常難受。序列化數(shù)據(jù)結(jié)構(gòu)必須帶版本號(hào)和遷移機(jī)制。好結(jié)構(gòu)是慢慢“長(zhǎng)”出來(lái)的沒(méi)有誰(shuí)第一版就能設(shè)計(jì)完美。允許數(shù)據(jù)模型演進(jìn)但演進(jìn)一定要有章法不能直接把舊數(shù)據(jù)處理邏輯撕了。圖系統(tǒng)的性能優(yōu)化以可視區(qū)裁剪為基底再疊加批量更新和分層渲染。這三板的收益在中小圖系統(tǒng)上已經(jīng)足夠真正需要 WebGL 的場(chǎng)景非常少不要過(guò)早引入重型技術(shù)。還有一個(gè)容易忽略的體驗(yàn)細(xì)節(jié)圖系統(tǒng)的空狀態(tài)。用戶打開編輯器時(shí)畫布上什么都沒(méi)有此時(shí)至少要展示一張“引導(dǎo)浮層”告訴用戶從哪里開始創(chuàng)建節(jié)點(diǎn)、怎么連線、怎么切換布局。這個(gè)浮層成本極低但對(duì)新用戶的上手體驗(yàn)幫助極大。很多圖系統(tǒng)做出來(lái)功能很強(qiáng)大但新用戶一打開就懵了很大原因是空狀態(tài)沒(méi)有設(shè)計(jì)過(guò)。我現(xiàn)在的習(xí)慣是每做一個(gè) diagram 類項(xiàng)目都會(huì)先從數(shù)據(jù)和布局入手搭一個(gè)最小原型只支持一個(gè)正方形節(jié)點(diǎn)、一條邊、一次拖拽、一次縮放跑通全鏈路后再逐步加功能。這個(gè)最小原型的價(jià)值不在于功能而在于把坐標(biāo)系、批量更新、撤銷棧、序列化這些地基打牢。地基穩(wěn)了后面長(zhǎng)出來(lái)的每一層功能才不至于傾覆。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
久热伊人| 热天堂一区二区| 欧美午夜色妇色鬼| 九九无码| 日韩精品怡红院| 黑人猛交| 天天摸夜夜摸| 国产无码三级视频在线观看| 台欧久久精品视频| 久久91| 日韩一级片在线看| 97超碰中文字幕| 黄片色区软件| 亚洲凸凹超碰成人| 日韩欧美中文日韩欧美色| 蜜臀亚洲综合一二三四区| 少妇综合网| 日本人妻一区二区| 青娱乐休闲视频在线观看| 熟女精品一区二区三区| 中文字幕在线免费观看 | 日本操逼视频不卡直接放| 在线观看十八禁| 久久久久久久97| 好吊色在线观看| 色综91| 欧州色图区| 亚洲精品久久久久毛片A片拉屎 | 婷婷色影院| 加勒比综合在线| 婷婷亚洲综合| 国产无码成人无码| 男女性扦B| 干B| 大黄片做爱的大的| 91免费看中出视频| 天天干天天日天天射黄色大片| 男女一进一出视频久久| 欧洲一区二区| 好看的91视频| 熟女视频久久| 高清孕妇孕交| 99热这里只有精品1| 精品-91人妻子系列| 久久精品黄色| 中文在线视频| 蜜臀久久99精品久久久久久久久| 福利视频香蕉免费一区二区在线| 污污污8888| 精品性爱无码在线播放| 手机在线A片| 另类图片五月天| 久久极品一区二区| 乱伦a片视频| 啊啊啊 在线| 97综合在线观看| 熟女乱伦A| 中文字幕av一区二区三区人妻少妇 | 女人18精品一区二区三区| 欧美亚洲激情小说| 国内精品久久久久影院亚洲| 国产无码成人无码| 夜夜嗨老熟女AV一区二区三区| 五月丁香久久| 99久久婷婷丁香| 试看60秒 爽| 蜜臀久久99精品| 韩国三级理论在线| 99久国产精品午夜性色福利| 人人摸人人入| 91色香| 青娱乐手机日韩在线视频| 亚洲中文字幕97久久精品少妇| 高清国产精品无码| 久久午夜色播影院免费高清| 天天性射网| 精品视频97| 99热这里只有精品99| 亚洲图片色图欧美另类| 韩国手机不卡无码三级视频| 国产91福利小视频在线观看| 国产一线二线三线av| 亚洲综合性网址| 91在线免费观看处女| 91干熟女| 欧美一区二区三区日韩| 久久性爱免费送| 看免费的黄片| 国内黄色精品| 国产一区96在线| 91性高潮久久久久久久久| 免费亚洲黄色视频在线观看| 国产精品自拍xxxx| 人人摸.人人色| 亚洲九九九| 91精品导航| 加勒比性爱成人在线| 亚洲色欲一区二区三区| 淫乱图区 | 欧洲中文字幕| 国产熟妇一区二区| yazhousetuoumei| oumeisetu综合| 在线日韩视频| 麻豆天美电影一区二区| 97WW精品| 蜜臀99999| 亚洲天堂另类小说男人| 色天堂综合| 国产精品经典一卡久久久 | 午夜婷婷| 91粉芽高清在线一区二区| 大香网伊人久久综合| 青青操轻轻| 久久精品国产免费观看99| 无码人妻丰满热妇又大又粗| 粉嫩绯色AV一区二区在线| 岛国艾薇凹凸视频天堂| av片在线观看免费播放| 激情五月天色色| 91一起操| 亚洲国产剧情少妇激情| av东京热男人的天堂| 国产日韩欧美| 熟女熟妇伦久久影院毛片一区二区| 欧美性五月| 精品免费囯产一区二区三区| 欧美色图综合| 无码精品一区二区三区潘金莲| 中日韩久久久| 狠狠干狠狠干| 欧美97日韩| 国产精品久久久久久久久久久久久久久| 91亚洲欧美色图| 97超碰这里只有精品| 啊啊啊男女| 超碰九区| 精品中文字幕一区二区| 亚洲九区| 中文字幕免费观看| 青娱乐妇女性生活| 人人摸人人添人人操 | 天天干天天日天天射黄色大片| 国产原创精品| 哑洲在线| se吧提供91精品国产91久久久久久 | 久操| 亚洲性爱成人| 97国产成人精品免费视频| 深夜啪啪啪视频免费| 亚洲男人的天堂一区二区| 日日橹狠狠爱欧美超碰| 天天天肏屄肏屄肏屄欧美欧美| 日韩成年人性爱视频| 九九综合久久中文字幕| 中欧人妻丝袜中文字幕| 精品久久久久久中文| 色色操| 欧美 亚洲 大香| 亚洲风情综合网| 伊人网青青| 婷婷大香蕉| 啊啊啊啊二区好大| 91老熟女| 亚洲高清无码免费观看视频| 亚洲97p| WWW.操逼.COM| 超碰在线看| 国产熟妇一区二区| 国产精品不卡高清在线观看| 人妻天天爽夜夜爽爽| 人人操人人射人人干| 9久久久久| 成人性爱av.com| 极品白嫩福利在线| 久久97精品久久久久久久不卡| 青青久久手机线视频| 国产欧美日韩女同性恋ww喷水精品 | 九九视频黄色片| 免费夜夜爱黄色视频毛片| 日韩不卡一二三四| 99久久久久久久久| 欧美日韩97在线| 国产高清在线观看欧美| 久草精品一区 | 天堂无码精品国产久| 午夜天堂精品久久| 亚洲熟妇一,二,三期| 香蕉久久国产AV一区二区| 婷婷精品国产一区二区三区日韩| 国产精品高清2021在线| 九九九久千久久激情蜜桃在线看 | 国产亚卅97| 少妇久久久| 天天狠| 97视频免费播放| 91超级碰碰碰| 久久精品国产亚洲av水密被窝| 免费操逼视频下载| 欧美淫乱视频| 欧美婷婷| 3p国产色噜噜一区| 大香蕉欧美国产日韩高潮| yellow网站免费观看日韩高清无码| 欧美劲爆视频一区二区| 天天拍天| 欧美很很操视频| 亚洲97网站| 国产激情av女片自拍| 激情视频一二三| 三级色综合| 亚洲大胆人体av| 性爱视频啪啪啪啪| 色九九九九九九| 国产激情片在线观看| 色网亚洲人| 志村玲子视频一区二区| 欧美性xxxxx狂欢| 人妻少妇精品一区二区三区| 日韩一级二级三级在线不卡观看完整| 亚洲精品一区二区三区新线路| 久操电影| 亚洲精品国产精品乱码不卡| 中国女人内射6XXXXX| 国产免费一区| 久久久久成人蜜桃精品| 奇米四色网| 久久久九九九九| 欧美一级做a爰片免费视频| 熟女91网| 嗯……啊…嗯嗯…啊…好舒服| 思思热国产高清| 日本男人插女人的逼黄色| 亚洲精品乱码线路中文字幕| 四虎精品永久在线观看| 天天看天天综合成人网| AV一区观看| 大香蕉在线SuP| 五月丁香综合| 国内毛片无遮挡国产| 97av,com| 色 婷97| 51久久夜色精品国产麻豆| 欧美伦乱爱| 国产日比| 国产中文精品一区二区在线观看| 欧美自拍网| 一区麻豆 高清中文字幕| 欧美日韩在线国产在线| AAAA级日本片免费视频| 白嫩白嫩的午夜九久久久久久久久久久久成人剧场 | 啊啊啊啊啊啊好湿好爽视频| 一区三区啪啪| 超碰无码加勒比| 成人一二三区| 中文字幕无码不卡啪啪| 久久成年精品| 欧美亚洲国产自久久| 国人欧美精品一区二区| 激情黄色片在线观看| 蜜臀无码一区二区| 亚洲色图a| 男人的天堂一区三区| 日韩性爱一级片| 久久久久女教师免费一区| 青青草男人天堂| 奸色色 男人天堂 天天射| 免费簧片在线观看| 91香蕉视频在线观看免费| 爱逼综合| 97干在线视频| 清纯唯美第一页| 91 综合 色| 国产久久一区二区三区野外在线| 超碰免费在线| 欧美一区二区亚洲天堂| 日韩视频啪啪| 丰满人妻一区二区三区大胸懂色| 370p日韩欧美亚洲精品| 青娱乐999| 蜜臀久久99精品久久久久久-DVD| 人人摸人人舔一区二区| 日日妻色网| 插老姨肥穴| 中文字暮97| 玖玖在线视频| 一区黄二区黄| 欧美久久久15P| 久久久工口| 久久啊哟| 天天弄欧美| 蜜桃视频精品一区二区三区| 打av高清| 亚洲精品一区二区免费在线观看| 九九热精彩视频| 蜜臀久久在线视频| 91久久堂| 91国产丝袜美女| 视频在线中文字幕| 四虎免费视频| 97在线免费看视频| 97在线视频观看| 国产精品久久久久中文字幕| 免费观看国产小粉嫩喷水精品午| 亚洲第一黄色av网站| 思思性爱| 综合熟女| 密臀AV在线| 亚洲色香| 后入合集| 久久精品福利影院| 不卡免费av在线播放| 久久久久久AⅤ无码免费肉站| 天天插天天操| 天天舔天天 | 国人欧美精品一区二区| 久久五月视频| 色婷婷综合久久久久中文一区二区| 尤物av网站| 亚洲黄日韩无码专区| 亚洲欧洲第二视频在线观看色图| 欧洲性人爱视频| 99热这里只有精品1| 一本大道青青| 中文色综合| 性色av网站| 99视频内射三四| 久久久久骚| 欧美视频激情久久久久久| 亚洲91综合| 亚州一区二区| 青青久久手机线视频| 亚洲AV无码乱码在线观看性色| 九九综合色| 任我爽视频在线观看| 亚洲色图国产另类| 国产熟女一区二区| 午夜福利1区2区3区| 手机看片1025| 亚洲自拍一区夜夜操| 91精品婷婷国产综合久久| 久久9久| 2021久久国产综合精品青草| 天天摸夜夜摸| 日韩99999| 99国产在线 精品 视频| 长长久久曰曰夜夜成人网| 超碰这里只有精品| 欧亚日韩一区在线| 国内自拍 日韩激情 99| 国产成自自拍在线观看| 欧美在线啊啊| 911粉嫩人妻| 国产激情久久久| 欧亚乱色熟一区二区三四区| 国产夫妻性生活视频| CCYY草草影院地址入口| 一区二区三区精品视频| 欧美日韩电影一区二区| 老熟女阿 国产91| 370p日韩欧美亚洲精品| 蜜臀av一区二区三区免费观看| 啊啊啊啊啊在线视频| 淫纸中9区| 日韩激情小说一区二区| 大香蕉AV丝袜| 久热精品在线| 日韩免费大片一级播放| 亚洲精品骚逼| 亚洲97超碰| 日本在线不卡v二区| 丰满人妻一区二区三区大胸懂色 | 97 亚洲 日韩 欧美 在线| 亚洲色图欧美色图制服丝袜| 欧美黑人熟妇精品91| 日操粉逼逼| 亚洲狼狼干综合1| 国产又长又大又粗的视频| 久久婷婷电影网| 五月天激情影院| 精国久久一区二区三区98| 97这里只有精品| 久久草在线综合视频| 天海翼久久| 国产午夜在线观看视频| 麻豆人妻少妇在线免费观看| 久久久久九九九九| 国产精品女同| 欧美综合另类| 亚州色图第三区| 亚洲日韩XXX| 操逼操逼逼操操逼91| 香蕉一区二区三区在线视频| 天天上日日上日韩精品| 午夜激情床戏激情| 国产精品一二三区18| 午夜免费视频1000| 超碰97人妻| 亚洲中文制服诱惑| 人人操人人摸人人看人人插| 97超碰碰碰| 国产97在线视频| 久久久一热在线播放| 亚州一区二区| 麻豆人妻精品一区二区| 国产精品久久久| 蜜臀久久99精品久久久久久久久| 伊人天天久久动态图| 91N五十路| 久久久久久久免费A片国产成a人亚洲精∨品无码 | 精品无码久久久久久久杏吧| 台欧久久精品视频| 久久性爱精品一区| 国产盗摄美女如厕大神作品在线观看| 中文字幕乱码人妻二区三区| 国产伊人精品在线| 欧州色图区| 亚洲无码成人精品| 欧美色图97| 精品区9| 12一15性XXXX粉嫩国产| 99黄页网站| 国内毛片无码一级毛片| 91视频综合网| 97视频在线观看网站| 国产精品久久久三级无码| 日韩少妇无码| 中文字幕、久久精品国产2020、久久综合久久自在自线精品自、亚洲 | 天美传媒婬乱在| 视频在线观看一二三区| 91人妻尻屄视频| 大香蕉伊人75| 成人A片男人的天堂| 日韩国产欧美伦理在线| 亚洲欧美不卡线| 精品无码一区二区| 久草资源在线视频官方总站日韩丝袜美腿 | 色999五月色| 97超碰精品| 欧洲大香蕉| 嗯啊视频免费在线观看| 色综九九九一区| 9 7超碰在线免费观看| 视频国产精品未满十八禁止在线观看| 欧美春色| 中文久久96| 国产免费一区二区在线A片视频| 亚洲人成在线放东京热| 不卡一区视频| 一区二区三区 丝袜 高跟 美腿| 欧美18 在线观看| 偷拍欧美亚洲| 男女91| 操逼日韩无码 | 一区二区三区在线日韩影院观看| 蜜桃色色网站视频三区| 免费啪啪一级视频| 密乳视频在线| 亚洲欧美九九九| 国产超碰人人爽人人做| 乱伦日本中文自拍| 91亚洲综合在线| 91激情国产| 诱惑人妻欧美一区在线播放| 色色婷婷五月天| 亚洲少妇中文字幕网址| 日韩无码操逼片| 九九草| 免看60秒涩涩视频| 美日韩在线不卡人妻| 一区二区偷拍拍视频| 熟女色综合久久| 色色色日本| 啊v在线观看视频| 欧美,亚洲,日韩,v,天堂,手机在线观看| 国产白嫩精品久久| 亚州精人品大香蕉| 婷婷操逼| 成人乱人伦一区二区| 日本不卡一区| 亚洲午夜蜜臀| 手机av亚洲丝袜美腿日韩第一页二页| 亚洲一二三精品久久网| 日韩AV电影网站| 成人性爱电影网| 黄色操人| 性暴力欧美猛交在线直播| 大JI巴好深好爽又大又粗视频| 国产精品69久久久久久久| 中文字幕78| 欧美一二在线| 蜜臀在线免费观看在线免费观看| 97超碰美国| 综合网欧美在线| 超碰免费人人| 狠狠操狠狠爱| 久久九色| 伊人AAA| 久久久婷| 免費人妻夜夜爽天天爽爽一区| 九九热免费视频| 亚洲中文字幕av| 色婷视频| 韩日精品四区| 夜夜操2028| 97人人操人人摸| 色一色综合网| 色婷五月天| 97国产精选| 精品9999| 国产精品久久蜜乳av| 亚洲成人在线乱码色午夜| 热热色色综合| 手机久操欧美综合色码| 日日干夜夜欢| 久草精品在线| 欧美人体性爱互联网第一页婷婷日本| 国产一级舔足在线观看| 翔田千里AⅤHD无码| 欧美性爱无码一区二区三区| 韩国午夜理伦三级好看| www超碰| 精品妇女一区二区三区| 青青草黑寡妇男人天堂| 18禁久极品美女久久哦哟呀!| 日本黄色天堂| 中文字幕三四区| 在线岛国新天堂8| 中文字幕一区电影在线观看| 亚洲欧洲国产综合av| 日日夜夜干| 免費人妻夜夜爽天天爽爽一区| 1区2区3区中文字幕日韩| 97视频在线视频| 天天干夜夜鈤| 国产狂喷潮在线精品| 欧美成人AⅤ大片在线观看| 免费看日产一区二区三区| 大香蕉伊人色偷偷在线| 黄日韩| 老熟女天天操| ..日韩av毛片精品久久久| 亚洲欧美激情在线视频| 热久久国产精品视频大陆精品| 91黄射| 无码137片内射在线影院| 中文字幕在线高清男人的天堂| 成人AV素股で擦久久| 亚州九九九精品视频| 无码137片内射在线影院| 欧美日韩国产色图在线| 超碰97男人| 国产视频大全| 色色毛片| 丁香五月影院| 狠插 制服 自拍| 欧美精品黑人猛交高潮| 日韩欧美综合激情| 很黄很污的免费网站| 亚洲欧美啪啪| 久久久久久一日韩字幕无码| 98一区二区精品| 亚洲综合伊人| 国产超碰AV在线精品| 97人人干| 亚洲熟久久| 亚洲网站一区二区在线| 亚洲高潮少妇| 色臀AV| 国产懂色精品国产av| 激情图片亚洲色图| 八戒午夜福利理论片| 亚洲第一页色| 欧美伊人电影| 欧美成人都市人妻| 99热在线只有精品| 亚洲超碰AV| 精品一二三区四视频| 国产女大学生AV| 五月婷婷综合在线| 久久久精选| 亚洲成人福利电影免费| 欧美91精彩| 日韩极品无码B| 人人污日韩一区二区| 欧美激情专区| 啊啊啊啊嗯嗯嗯用力好爽 | 91激情综合| 日本 色 导航| 日夜干射色啊| 天天干一区二区| 日韩欧美蜜桃精品久久中文字幕久久 | 色婷婷综合久久久久中文国产精品一区中文字幕,国产福利电影一区二区三区 | 国产国产亚洲一二三久久| 久久久久久国产无码精品| 99国产精品人妻人伦| 天天草天天日| 第二页中文字幕| 久久熟女精品不卡一区| 欧美做爰无码A片视频| 国产超碰欧美| 久久久久亚洲?V片无码V| 啊好爽快点-国产一区二区三区撒尿在线-成人AV| 又大又大又大又粗爽高潮观看| 屌逼麻豆| 欧美激情综合| 久偷拍| 亚洲国产综合视频| 日本熟人妻中文字幕在线|...久久国产精品-国产精品_日本一区二区三区中文字幕 | 老司机午夜精品视频| 人人操天天爽| 成人免费看吃奶视频网站| 欧美视频激情久久久久久| www..com操老师| 亚洲色图国产另类| 天天日天天干天天整| 欧美瑟综合| 伊人亚洲国产一成人久久精品,久久| 亚洲综合网91| 黄色高清久久无码依人| 黄色区免费观看中文字幕| 久久久成人免费av电影| 99在线精品视频| 欧美成人免费在线观看| 天天看高清麻豆| 五月丁香影视| 亚洲国产欧美一区二区潘金莲| 国产精品在线网站| 亚洲综合成人网| 91丝袜| 天天综合~91入口| 亚洲精品一区二区精品| 午夜福利一区二区三区四区五区色婷婷| 九九色婷婷| 日本精品一级二级三级| 少妇人妻激情四射| 毛片中心9视频99| 成人七区| 青青色在线观看| 亚洲 欧美 另类 日韩 人妻一区| 欧亚在线视频| 国产精品福利资源在线尤物| 国产精品欧美激在线| 久操热线| 九月激情婷婷| 无码精品久久久久久亚洲| 人妻激情在线视频| 亚洲成人综合在线| 青娱乐淫乱1314| 日韩中文字幕2020| 日本午夜福利影院| 三级激情网站| 69精品| 天天爱综合网| 伊人网在线观看| 男男H黄动漫啪啪无遮挡网站| 精品综合久久久久久五月天| 久久99久久99精品天美传媒棢·纸:. | 婷婷10月天青娱乐| h色99999| 中文字幕视频2区| 操逼操操操91| 无码操逼网| 人妻一区二区三区四区视频| 欧美性爱视频免费一区一A| 欧美激情性久久久久久| 亚洲国产精品成人久久蜜臀| 欧美人妻一区二区| 亚洲天堂美臀在线| 操b网站亚洲无码| 久草婷婷| 欧美最婬乱婬爆婬性视频| 97色碰| 99综合| 爆操无码| 超碰在线国产| 男人的天堂一区三区| 乱伦图一区| 嫩草影院在线观看精品| av天堂精品久久| 性爱视频免费网址| 国产高清成人免费视频| 岛国网址国产| 国产日韩手机视频在线| 五月亭亭六月丁香| 日本伦理一区二区| 青青久草| 色色无码| 97超碰日韩| 嗯~啊~快点 死我视频| 欧美后入| 熟妇艹鸡八| A一区片| 性生活久久久久久久久久| 精品国产一区探花在线观看| 天天干一区二区| 久久免费99精品久久久久久| 97超碰久| 国产 日韩 欧美 中文 另类,国产 欧美 另类 制服 变态,高清 日韩 欧美 中文,高 | 亚洲第一页色网| 丁香五月综合| 大色综合| 亚州再线| 伊人五月天激情| 欧美激情在线观看视频| 丁香激情网| 农村女一级毛卡片| 男生女生啊啊啊啊| 岛国片国产成人亚洲播放| 97ai亚洲| 亚洲天堂另类美腿| 亚洲阿v天堂无码z2018| 884t在线| 大香网站| 色97欧美| 91国产丝袜足交精品视频| 精品国产Av无码久久久亚洲| 爱爱久久| 国产日本久久免费精品| 人妻少妇久久中文字幕一区二区 麻豆 | 国模无码人体一区二区三| 久久啊啊啊视频| 日韩精品在线观看观看| 情色五月天就去干| 综合网欧美在线| 少妇3P性爱自拍| 99热精品在线观看| 狠狠中文字幕| 蜜臀AV秘一区翔田千里| 亚洲91射| 黑丝少妇麻豆| 国产美女销魂在线观看不卡| 夜夜春夜夜操| 宅男91视频在线播放| 中文字幕aⅴ在线视频| 欧美日韩另类激情图片| 日韩伦理视频| 超碰在线成人| 国产精品99精品视频网站| 国产青青综合伊人| 麻豆国产av网| 国产一区二区视频在线播放| 狠狠操使劲操| 久久精品中文| 91狠婷| α√在线| 色综合av综合久久| 欧美日韩国产精品久久色婷婷| 精品妇女一区二区三区| 人人操人人操草草| 三上悠亚在线毛片91| 东方亚洲在线操逼天堂| 97网址www| 一个人免费HD91视频| 日韩欧无码一区二区三区免费不卡 | 四虎在线观看网站| 美女露胸露奶头| 六十路日本| 免费观看性欧美一级| 国产日本顶级一区二区三区| 国模不卡一本二本三电影| 国产激情综合五月久久| 天堂俺去俺来也www久久婷婷| 不卡视频一区蜜桃视频 | 欧色性第一页| av午夜玫瑰| 骚逼高潮久久精品| 日本99热| 全免费a敌肛交毛片免费| 91精品人妻一区二区三区蜜桃| 九九九九九九九九九九九九九九九女| 一品道视频一区二区三区| 久久婷婷精品| 少妇高潮对白在线观看| 成人性爱av.com| 在线人成亚洲视频免费观看| 久久久久久久久女黄| 好看的久久不射无码影视影院| 亚洲丁香花色| av资源在线观看少妇| 能在线播放的国产三级| 国产啊v在线免费播放| 日韩欧无码一区二区三区免费不卡| 四虎影视国产精品| ...日韩成人一区二区三区字幕| 淫色网综合| 骚货人妻偷情自拍在线视频| 97精品综合久久| 密乳无码| 中文字幕一二区二三区人妻专区| 草草草视频在线免费看| 蜜臀网 一区| 天天操天天谢| 嗯嗯啊啊用力视频免费| 美女人妻色网站| 日韩人妻少妇 一区二区三区| 天天操天天干一区二区 | 国产欧美一区二区| 天天日老熟妇| 玖玖综合色| 蜜桃臀 后入 一区 二区 三区 在线| 九九热免费国产视频婷婷伊人| 五月婷丁香| 91人妻超碰| 熟女啪啪视频| 国产丰满少妇久久久精品影院| 中文字幕少妇色 | 有码人妻系列| 丝袜视频一区二区在线播放国产中文| 欧美色九九九| 欧美五区| 妇女视频网站| 国产久久一区二区| 91欧美性| 四虎影视 亚洲无码| 99re28在线观看| 美女啊啊啊啊啊啊| 在线αⅴ| 亚洲一区二区三区不卡国产欧美| 国产不卡免费在线视频| 亚洲制服欧美另类内射| 很很干很很操| 中文字幕视频2区| 狠狠2050在线观看| 天天综合站| 天天影视综合色| 欧美综合网在线| 91人妻人人澡人人爽人人精品| AAAA级日本片免费视频 | 国产狂喷潮在线精品| 综合国产影视三级| 国产精品激情久久久久久久| 熟女突然公开看18禁影片 | 亚洲天堂一二| 欧美色图 色综合图| 蜜臀一区二区三区在线| 久久欲| 日本视频在线观看污污污| 国产 日韩 另类 视频一区爱| 99久在线精品99re8热| 中美日韩毛片| 999 久久久| 91精品在线播放| 99人妻| 欧美日韩电影成人在线| 99精品成人免费看| 综合色图,成人综合网| 久久久久久久久九九久孕交| 亚洲黄色网址| 日韩99999| 免费A片三p视频| 免费观看的黄色的网站| 大香蕉综合网| 日韩ab网| 96超碰网| 亚洲激情在线观看一区| 国产一区二区欧美日本| 精品国产乱码久久久久A| 神马久久久久久久久久| 五月天婷婷社区| 成人a v在线播放免费| 曰韩无码777| 嗯嗯啊啊亚欧精品| 91亚洲网站| 婷婷丁香九月| 97视频网站在线观看| 国产精品丝袜久久亚洲不卡| 精品一区二区三区丰满熟女-亚洲欧美一区| 免费看片黄| 亚洲.欧美.丝袜.中文.综合| 好屌色综合| 一区二区三区高清 | 黄色网址在线免费观看| 亚洲图片欧美日韩| 偷拍99| 欧美性爱18观看| 欧美精品人妻视频| 日韩中文9| 欧美春色| 91三级理论片播放器| 国产黄a三级三级三级av在线看 | av 模特一区了| aa片毛片| 久久久成人国产精品无码| 黑丝91视频| 97操碰| 蜜乳av一区二区| 欧美综合骚| 后入日本1234| 强被迫伦姧在线观看无码网站| 一级免费啪啪片| 好舒服视频| 中文字幕一品色图| 青春草莓视频在线观看网址| 立川理惠加勒比无码| 久操在97| 国产二区三区免费视频| av天堂5| 日韩精品电影| 欧美呦呦性爱| 97视频网站在线观看| 久久99草| 成人av影院在线观看| 九九亚洲视频| 国产欧美日产一区二区三区 - 国产欧美日 | 亚洲欧美日韩精品久| 久久精9| 国产精品直播在线观看直播| 青青草丝袜在线视频| 狠狠爱夜夜干| 少妇人妻太紧太深av| 欧美日本久久精品一区 | 2019天天干天天操| 午夜精品久久久久| 一级性爱视频免费在线| 白嫩嫩一区| 亚洲国产97| 91大学精品激情戏| 校园激情狠狠四射| 久久人妻办公室视频| 校园春色宗合网| 国产辣妈在线视频福利| 日韩一区二区熟女| 国产精品一区二区亚洲人成毛片 | 国产视频大全| 丰满人妻一区二区三区四区| 色妇91| 91快色色色色色| 学生妹天天看| 国产区91柔拿会所技师| 久久久久密臀视频| 午夜福利在线合集| 91无摭挡| 在线国产福利网址导航| 大香蕉综合在线| 999国产精品999| 国产自偷| 天天干,夜夜爽| 日本久久久精品电影| 亚洲精品无码久久AV| 久久熟女久| 婷婷视频在线免费观看| 综合熟妇一区二区三区| 狠狠操综合| 欧美综合综合| 亚洲第一页色| 日本成人在线不卡一区二区三区| 超AV色女| 啪啪啪精品| 欧美日韩电影一区二区| 久久久久久久伊人精品| 日本丝袜美腿人妻九九| 美女视频尤物网在线看| 色色99| 天天色天天干天天爱| 亚洲性少妇| 操逼网免费无码视频| 竹菊一区二区三区AV线| 99热97| 九九精品99| 狠狠色五月亚洲91| 国产人妻精品久久久一区二区三区 | 骚货操死你| 日韩中文字幕熟妇人妻| 香蕉热人人精品| 欧美的精品的视频| 日产国产精品中文久久婷婷| 玖玖爱免费观看视频| 啊啊啊水好多| 天天干天天日天天射黄色片| 东京热男人的天堂精品| 99热在线只有精品| 91蜜臀在线久久久久| 摸奶性爱视频网站在线免费播放| 加勒比海成人视频网| 麻豆这里只有精品| 2024年最新色情网站在线观看 | 国产天美欧美| 欧美精品二区视频在线| 人妻精品一区一区三区蜜桃91| 啊啊啊不要好疼视频| 亚洲密乳AV| 色噜噜人妻av中文字幕| 精品久久99| 中日韩欧美精品无码AⅤ一区二区| 久久欧美激情| 你草精品在线视频| 无码视频黄色网战| 伊人热综合| 欧美综色欧| 天天做天天爱天天爽AV| 五月激情在线| 国产精品国产自产高清AV| 久久免费少妇| 婷婷15月天青娱乐| 爱爱60秒免费视频| 国产日本久久免费精品| 无码高清操逼| 999精品女人| 色香伊人| 日本人妻天堂网站在线播放| 97色婷婷| 日韩黄色成人性爱| 欧美久久人人网| 久久男人的天堂| 偷拍导航视频网站| 高跟伊人julia ann| 91蜜臀在线久久久久| 一级久久久久久久久久久| 影音先锋新男人| 欧美碰碰综合色| 久久九操在线观看| 97在线无精品| 久无码| 天天添天天干电影| 午夜120视频在线观看| 亚洲春色欧美激情自拍| 欧洲人妻视频| 中文熟女五十乱码在线| 成人色女网| 欧美亚洲综合色| 五月丁香| 熟女视频久久| www.91理论| 强奸乱伦 亚洲一区| 日韩性色| 五月天AV资源| 激情视频一二三| 麻豆精品久久久久久久| 青青草日韩无码| 日韩精品中文字幕二区| 岛国黄| 亚洲男人久久综合天堂| 久久久96| 亚洲色欧| 九一国产精品| 久久中文字幕女同性恋一区| 999日韩中文精品观看视频。| 日本99久久| 人人操人人摸人| 伦伦成年午夜免费视频| 99国产在线 精品 视频| 日日操免费视频| 亚洲色欲天天天堂色欲网女| 成 人 A V免费视频在线观看| 密臀在线一区尤物| 日韩97视频| 国产精品午夜福利视频| 亚洲图片在线| 97在线资源| 在线情色电影 91大| 97网址97| 97精品久久久久中文字幕| 国产精品丝袜久久亚洲不卡| 91扒丝袜综合在线| 中国黑人三级片网站上区| 四虎视频在线观看| 97色色色综合网站| 青青草字幕AV| 亚洲性图91| 久久熟女精品不卡一区| 久草这里只有精品 | 国产高清自拍视频| 日韩无码极品| 亚洲人成网站7777| 日本熟女免费視颖| 久久这里是精品| 最好看的中文字幕在线2018| 亚洲影院无码在线| 日婷婷| 亚洲欧美日韩精品久久久一区二区| 黑人精品一区二区在线播放| 国产一区二区三三视频| 极品销魂美女一区二区| 日韩特级毛片免费观看全集| 久久久久久亚洲中文| 少妇高潮特黄A片| 五月婷婷色色| 日韩二级| 欧美亚洲高清不卡| 亚洲高潮影院| 成人性生活高清视频在线播放| 亚洲春色一区二区三区| 色婷婷激一区二区三区 | 久久香蕉影院| 中文字幕日韩人妻视频一区二区三区 | 人人透人人操| 大香蕉久久| 97亚洲国产影视| 青青草久草AV| 国产又粗又长又大的视频| 外国91| 欧美一区二区三区四区综合| 操逼1区| 九热视频| 久久不卡一区二区| 夜夜爽爽夜夜精品视频| 久久大香蕉97| 国产综合色精品在线观看| 午夜寂寞欧美| 九九九九九九九精品视频| 日本九九久久99播| 日本亚欧爱爱| 一区二区高清视频| 亚洲乱码国产乱码精网站| 国产精品久久成人免费| 91色插| 艾草av| 欧美激情一| 亚洲黑人在线| 久久黄色视频一区二区三区| 久久视频,这里只有精品| 一卡二卡三卡| 欧美v亚洲v综合v国产v妖精| 在线无码操| 日韩无码嘿咻黑热久| 青青草一区二区三区四| 摸奶性爱视频网站在线免费播放| 亚洲欧美在线观看2021| 国产精品熟女AV中文字幕在线播放| 天天干夜夜| 国产成人在线观看网址| 岛国成人av在线播放网址| 丁香婷婷激情五月天无毒不卡| com 首页 18岁 禁区 女优 免费 精选 同城 | 激情五月天色色| 日韩精品怡红院| 熟妇女伦乱视频| 岛国网址国产 | 911粉嫩人妻| 欧美中文狠| 91性情| 最近的最新的中文字幕视频| 亚洲AV无码久久精品蜜桃小说| 啊啊啊啊好疼| 成人福利视频网| 人妻天天爽夜夜爽精品2| 亚洲欧美精品久| 嗯嗯啊啊操我| 日韩成人大片一区二区| 亚洲人妻熟妇三十三区| 狠狠躁伊人中文字幕| 国产黄色小视频网站| 午夜免费视频1000| 97伦综合| 中文字幕精品一区二区精| 美女人妻色网站| 91美女视频电影| 国产精品69人妻无码久久久| 久久久啊啊| 91日产桃蜜| 亚洲另类电影| 色臀aV| 婷婷在线视频在线观看| 久九干| 欧美激情高清性猛交| 人人摸人人叼| 欧美精品欧美精品系列| 天天色,天天干,天天干| 久久精品视频久久久|