Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲精品中文字幕在线,国产精品久久久久久久专区,日本三线免费视频观看

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          前端必備知識點(diǎn)—Canvas(畫布)

          天小編將分享前端開發(fā)中必學(xué)的知識點(diǎn),HTML5中關(guān)于Canvas(畫布)的知識點(diǎn);

          基本內(nèi)容

          Canvas,是HTML5中所有新特性目前應(yīng)用最廣泛的一個(gè)標(biāo)簽,替代引入的圖片(圖形),用途非常廣泛如(因此這個(gè)標(biāo)簽相當(dāng)重要):

          1.完成HTML頁面中的圖形繪制

          2.實(shí)現(xiàn)網(wǎng)絡(luò)游戲或單機(jī)游戲(網(wǎng)頁游戲)

          3.在HTML頁面中繪制圖表

          4.餅狀圖

          5.柱狀圖

          6.折線圖

          7.網(wǎng)頁游戲

          ...

          Canvas的發(fā)展方向,目前主流的游戲開發(fā)引擎之一,如:白鷺引擎 - HTML5、Cocos-JS - HTML5、掌握物理系統(tǒng)、掌握精靈系統(tǒng)(地圖)、HTML5網(wǎng)頁游戲。

          需要特別注意的是:Canvas作為HTML頁面的元素出現(xiàn)、在Canvas繪制的圖形與HTML頁面是無關(guān)的、利用DOM定位繪制的圖形、元素的事件不能綁定繪制的圖形

          如何使用Canvas(分2步驟)

          HTML頁面部分:定義<canvas>元素、建議使用width和height屬性設(shè)置<canvas>元素的寬度和高度

          JavaScript部分:獲取HTML頁面中的<canvas>元素、通過getContext()方法創(chuàng)建畫布對象、該方法接收一個(gè)參數(shù) - 創(chuàng)建二維或三維圖形

          需要特別注意的是該參數(shù)為字符串類型、"2d"或"3d"中的"d"必須小寫、目前幾乎都是"2d"效果、使用Canvas提供的API完成需求。

          常見的應(yīng)用

          應(yīng)用一:繪制圖形

          fillRect(x,y,width,height) - 繪制實(shí)心矩形

          x和y - 表示繪制矩形的左上角的坐標(biāo)值(x,y)

          width - 表示繪制矩形的寬度

          height - 表示繪制矩形的高度

          strokeRect(x,y,width,height) - 繪制空心矩形

          x和y - 表示繪制矩形的左上角的坐標(biāo)值(x,y)

          width - 表示繪制矩形的寬度

          height - 表示繪制矩形的高度

          clearRect(x,y,width,height) - 清除指定區(qū)域的矩形

          x和y - 表示繪制矩形的左上角的坐標(biāo)值(x,y)

          width - 表示繪制矩形的寬度

          height - 表示繪制矩形的高度

          設(shè)置樣式

          fillStyle - 設(shè)置填充樣式

          strokeStyle - 設(shè)置描邊樣式

          globalAlpha - 設(shè)置透明度(0-10-100-10-1000-10-1000000-10-10000-10-10000-10-10000-10-10000-10-1000-10-100000-100-100-1)

          需要特別注意的是:先設(shè)置樣式,再繪制圖形,每改變一次樣式,都需要重新設(shè)置樣式,填充樣式與描邊樣式互不干擾

          應(yīng)用二:線性漸變

          createLinearGradient(x1,y1,x2,y2)

          線性漸變具有一個(gè)基準(zhǔn)線

          射線(扇形)漸變

          createRadialGradient(x1,y1,r1,x2,y2,r2)

          射線漸變具有兩個(gè)基準(zhǔn)圓

          設(shè)置漸變顏色

          addColorStop(position,color)方法

          color - 顏色

          實(shí)現(xiàn)步驟如下:

          1.設(shè)置線性漸變或扇形漸變

          2.返回漸變對象

          3.漸變對象設(shè)置漸變的顏色

          4.設(shè)置填充或描邊樣式為漸變

          應(yīng)用三:繪制文字

          設(shè)置屬性:font - 用法與CSS中的font一致

          對齊方式:

          textAlign - 水平對齊

          left - 基準(zhǔn)線在文字的左邊

          center - 基準(zhǔn)線在文字的中間

          right - 基準(zhǔn)線在文字的右邊

          textBaseline - 垂直對齊

          top - 基準(zhǔn)線在文字的上邊

          middle - 基準(zhǔn)線在文字的中間

          bottom - 基準(zhǔn)線在文字的下邊

          hanging - 懸掛基線

          alphabetic - 字母基線

          繪制方法

          fillText(text,x,y) - 繪制實(shí)心文字

          text - 設(shè)置繪制的文字內(nèi)容

          x和y - 設(shè)置繪制文字的坐標(biāo)值

          strokeText(text,x,y) - 繪制空心文字

          text - 設(shè)置繪制的文字內(nèi)容

          x和y - 設(shè)置繪制文字的坐標(biāo)值

          設(shè)置陰影

          shadowColor - 設(shè)置陰影顏色

          shadowOffsetX - 設(shè)置陰影水平位置

          正值 - 陰影向右移動(dòng)、0 - 陰影不移動(dòng)、負(fù)值 - 陰影向左移動(dòng)

          shadowOffsetY - 設(shè)置陰影垂直位置

          正值 - 陰影向下移動(dòng)、0 - 陰影不移動(dòng)、負(fù)值 - 陰影向上移動(dòng)

          shadowBlur - 設(shè)置陰影的程度

          值的類型為Number、值越大,陰影效果越明顯

          VG 動(dòng)畫有很多種實(shí)現(xiàn)方法,也有很大SVG動(dòng)畫庫,現(xiàn)在我們就來介紹 svg動(dòng)畫實(shí)現(xiàn)方法都有哪些?

          一、SVG 的 animation

          SVG animation 有五大元素,他們控制著各種不同類型的動(dòng)畫,分別為:

          • set
          • animate
          • animateColor
          • animateTransform
          • animateMotion

          1.1、set

          set 為動(dòng)畫元素設(shè)置延遲,此元素是SVG中最簡單的動(dòng)畫元素,但是他并沒有動(dòng)畫效果。

          使用語法:

          <set attributeName="" attributeType="" to="" begin="" />
          • attributeName :是要改變的元素屬性名稱。
          • attributeType :是表明attributeName屬性值的列表,支持三個(gè)固定參數(shù) CSS/XML/auto,如x,y以及transform屬于XML,opacity屬于CSS。auto是瀏覽器自動(dòng)判別的意思,也是默認(rèn)值,如果你不知道該選哪個(gè)就填auto,瀏覽器自己判別。
          • to :動(dòng)畫結(jié)束的屬性值。
          • begin :動(dòng)畫延遲時(shí)間。

          eg:繪制一個(gè)半徑為200的圓,4秒之后,半徑變?yōu)?0。

          <svg width="320" height="320">
           <circle cx="0" cy="0" r="200" style="stroke: none; fill: #0000ff;">
            <set attributeName="r" attributeType="XML" to="50" begin="4s" />
           </circle>
          </svg>

          1.2、animate

          是基礎(chǔ)的動(dòng)畫元素,實(shí)現(xiàn)單屬性的過渡效果。

          使用語法:

          <animate 
           attributeName="r" 
           from="200" to="50" 
           begin="4s" dur="2s" 
           repeatCount="2"
          ></animate>
          • from :過渡效果的屬性開始值。
          • to:過渡效果的屬性結(jié)束值。
          • begin:動(dòng)畫開始時(shí)間。
          • dur:動(dòng)畫過渡時(shí)間,控制動(dòng)畫速度。
          • repeatCount:動(dòng)畫重復(fù)次數(shù)。

          eg:繪制一個(gè)半徑為200的圓,4秒之后半徑在2秒內(nèi)從200逐漸變?yōu)?0。

          <circle cx="0" cy="0" r="200" style="stroke: none; fill: #0000ff;">
           <animate attributeName="r" from="200" to="50" 
            begin="4s" dur="2s" repeatCount="2"></animate>
          </circle>

          1.3、animateColor

          控制顏色動(dòng)畫,animate也可以實(shí)現(xiàn)這個(gè)效果,所以該屬性目前已被廢棄。

          1.4、animateTransform

          實(shí)現(xiàn)transform變換動(dòng)畫效果,與css3的transform變換類似。實(shí)現(xiàn)平移、旋轉(zhuǎn)、縮放等效果。

          使用語法:

          <animateTransform attributeName="transform"  type="scale" 
           from="1.5" to="0" 
           begin="2s"  dur="3s" 
           repeatCount="indefinite"></animateTransform>
          • repeatCount:重復(fù)次數(shù),設(shè)置為 indefinite 表示無限循環(huán),一直執(zhí)行。
          • type:添加 transform 變換類型。
          • eg:繪制一個(gè)半徑為200的圓,4秒之后開始縮放,在2秒內(nèi)從1.5縮小到0倍。
          <svg width="320" height="320">
           <circle cx="0" cy="0" r="200" style="stroke: none; fill: #0000ff;">
            <animateTransform attributeName="transform" begin="4s"  
             dur="2s" type="scale" from="1.5" to="0" 
             repeatCount="indefinite"></animateTransform>
           </circle>
          </svg>

          1.5、animateMotion

          可以定義動(dòng)畫路徑,讓SVG各個(gè)圖形,沿著指定路徑運(yùn)動(dòng)。

          使用語法:

          <animateMotion 
           path="M 0 0 L 320 320" 
          begin="4s" dur="2s"></animateMotion>
          • path:定義路徑,使用語法與《HTML5(八)——SVG 之 path 詳解》path的d屬性一致。
          • begin:延遲時(shí)間。
          • dur:動(dòng)畫執(zhí)行時(shí)間。

          eg:繪制一個(gè)半徑為10的圓,延遲4秒從左上角運(yùn)動(dòng)的右下角。

          <svg width="320" height="320">
           <circle cx="0" cy="0" r="10" style="stroke: none; fill: #0000ff;">
            <animateMotion 
             path="M 0 0 L 320 320" 
             begin="4s" dur="2s"
             ></animateMotion>
           </circle>
          </svg>

          實(shí)際制作動(dòng)畫的時(shí)候,動(dòng)畫太單一不酷,需要同時(shí)改變多個(gè)屬性時(shí),上邊的四種元素可以互相組合,同類型的動(dòng)畫也能組合。以上這些元素雖然能夠?qū)崿F(xiàn)動(dòng)畫,但是無法動(dòng)態(tài)地添加事件,所以接下來我們就看看 js 如何制作動(dòng)畫。

          二、JavaScript 控制

          上篇文章我們介紹js可以操作path,同樣也可以操作SVG的內(nèi)置形狀元素,還可以給任意元素添加事件。

          給SVG元素添加事件方法與普通元素一樣,可以只用on+事件名 或者addEventListener添加。

          eg:使用SVG繪制地一條線,點(diǎn)擊線條地時(shí)候改變 x1 ,實(shí)現(xiàn)旋轉(zhuǎn)效果。

          <svg width="800" height="800" id="svg">
              <line id="line" x1="100" y1="100" 
              x2="400" y2="300" 
              stroke="black" stroke-width="5"></line>  
            </svg>
          <script>
           window.onload = function(){
            var line = document.getElementById("line")
            line.onclick = function(){
             let start = parseInt(line.getAttribute("x1")),
                 end=400,dis = start-end
             requestAnimationFrame(next)
             let count = 0;
             function next(){
              count++
              let a = count/200,cur = Math.abs(start+ dis*a)
              line.setAttribute('x1',cur)
              if(count<200)requestAnimationFrame(next)
             }
            }
           }
          </script>

          js制作的SVG動(dòng)畫,主要利用 requestAnimationFrame 來實(shí)現(xiàn)一幀一幀的改變。

          我們上述制作的 SVG 圖形、動(dòng)畫等,運(yùn)行在低版本IE中,發(fā)現(xiàn)SVG只有IE9以上才支持,低版本的并不能支持,為了兼容低版本瀏覽器,可以使用 VML ,VML需要添加額外東西,每個(gè)元素需要添加 v:元素,樣式中還需要添加 behavier ,經(jīng)常用于繪制地圖。由于使用太麻煩,所以我們借助 Raphael.js 庫。

          三、Rapha?l.js (拉斐爾)

          Raphael.js是通過SVG/VML+js實(shí)現(xiàn)跨瀏覽器的矢量圖形,在IE瀏覽器中使用VML,非IE瀏覽器使用SVG,類似于jquery,本質(zhì)還是一個(gè)javascript庫,使用簡單,容易上手。

          使用之前需要先引入Raphael.js庫文件。cdn的地址為:https://cdn.bootcdn.net/ajax/libs/raphael/2.3.0/raphael.js

          3.1、創(chuàng)建畫布

          Rapheal有兩種創(chuàng)建畫布的方式:

          第一種:瀏覽器窗口上創(chuàng)建畫布

          創(chuàng)建語法:

          var paper = Raphael(x,y,width,height)

          x,y是畫布左上角的坐標(biāo),此時(shí)畫布的位置是絕對定位,有可能會與其他html元素重疊。width、height是畫布的寬高。

          第二種:在一個(gè)元素中創(chuàng)建畫布

          創(chuàng)建語法:

          var paper = Raphael(element, width, height);

          element是元素節(jié)點(diǎn)本身或ID width、height是畫布的寬度和高度。

          3.2、繪制圖形

          畫布創(chuàng)建好之后,該對象自帶SVG內(nèi)置圖形有矩形、圓形、橢圓形。他們的方法分別為:

          paper.circle(cx, cy, r); // (cx , cy)圓心坐標(biāo) r 半徑
          paper.rect(x, y, width, height, r); // (x,y)左上角坐標(biāo) width寬度 height高度 r圓角半徑(可選)
          paper. ellipse(cx, cy, rx, ry); // (cx , cy)圓心坐標(biāo) rx水平半徑 ry垂直半徑

          eg:在div中繪制一個(gè)圓形,一個(gè)橢圓、一個(gè)矩形。

          <div id="box"></div>
          <script>
           var paper = Raphael("box",300,300)
           paper.circle(150,150,150)
           paper.rect(0,0,300,300)
           paper.ellipse(150,150,100,150)
          </script>

          運(yùn)行結(jié)果如下:

          除了簡單圖形之外,還可以繪制復(fù)雜圖形,如三角形、心型,這時(shí)就使用path方法。

          使用語法:paper.path(pathString)

          pathString是由一個(gè)或多個(gè)命令組成,每個(gè)命令以字母開始,多個(gè)參數(shù)是由逗號分隔。

          eg:繪制一個(gè)三角形。

          let sj = paper.path("M 0,0 L100,100 L100,0 'Z'")

          還可以繪制文字,如果需要換行,使用 \n 。

          文字語法:paper.text(x,y,text)

          (x,y)是文字坐標(biāo),text是要繪制的文字。

          3.3、設(shè)置屬性

          圖形繪制之后,我們通常會添加stroke、fill、stroke-width等讓圖形更美觀,Raphael使用attr給圖形設(shè)置屬性。

          使用語法:circle.attr({"屬性名","屬性值","屬性名","屬性值",...})

          如果只有屬性名沒有屬性值,則是獲取屬性,如果有屬性值,則是設(shè)置屬性。

          注意:如果只設(shè)置一個(gè)屬性時(shí),可以省略‘{}’。如:rect.attr('fill','pink')

          eg:給上邊的矩形添加邊框和背景色。

          <div id="box"></div>
          <script>
           var paper = Raphael("box",300,300)
           let rect = paper.rect(100,100,150,200)
           rect.attr({'fill':'red','stroke':'blue','stroke-width':'10'})
          </script>

          3.4、添加事件

          RaphaelJS一般具有以下事件:
          click、dblclick、drag、hide、hover、mousedown、mouseout、mouseup、mouseover等以及對應(yīng)的解除事件,只要在前面加上“un”就可以了(unclick、undblclick)。

          使用語法:

          obj.click(function(){
           //需要操作的內(nèi)容
          })

          3.5、添加動(dòng)畫

          animate為指定圖形添加動(dòng)畫并執(zhí)行。

          使用語法:

          obj.animate({
           "屬性名1":屬性值1,
           "屬性名2":屬性值2,
            ...
          },time,type)

          屬性名和屬性值就根據(jù)你想要的動(dòng)畫類型加就ok。

          time:動(dòng)畫所需時(shí)間。

          type:指動(dòng)畫緩動(dòng)類型。常用值有:

          • linear - 線性漸變
          • ease-in | easeIn | < - 由慢到快
          • ease-out | easeOut | > - 由快到慢
          • ease-in-out | easeInOut | <> - 由慢到快再到慢
          • back-in | backIn - 開始時(shí)回彈
          • back-out | backOut - 結(jié)束時(shí)回彈
          • elastic - 橡皮筋
          • bounce - 彈跳

          eg:點(diǎn)擊矩形,矩形緩緩變大。

          <div id="box"></div>
          <script>
           var paper = Raphael("box",800,500)
           let rect = paper.rect(100,100,150,100)
           rect.attr({'fill':'red','stroke':'blue','stroke-width':'10'})
           rect.attr('fill','pink')
           rect.click(function(){
            rect.animate({
             "width":300,
             "height":300
            },1000,"bounce")
           })
          </script>

          復(fù)制上邊的代碼,分別在各個(gè)瀏覽器和低版本IE瀏覽器運(yùn)行,發(fā)現(xiàn)都可以正常運(yùn)行。SVG的動(dòng)畫庫挺多了,我們介紹了拉斐爾,有興趣的小伙伴可以自行找找其他庫。

          據(jù)地圖平臺是字節(jié)跳動(dòng)內(nèi)部的大數(shù)據(jù)檢索平臺,每天近萬的字節(jié)員工在此查找所需數(shù)據(jù)。數(shù)據(jù)地圖通過提供便捷的找數(shù),理解數(shù)服務(wù),大大節(jié)省了內(nèi)部數(shù)據(jù)的溝通和建設(shè)成本。

          數(shù)據(jù)血緣圖譜介紹

          字節(jié)的數(shù)據(jù)可分為端數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù),這些記錄往往需要通過加工處理才能產(chǎn)生業(yè)務(wù)價(jià)值。數(shù)據(jù)加工處理的流程一般是讀取原始數(shù)據(jù),進(jìn)行數(shù)據(jù)清洗,再經(jīng)過多種計(jì)算和存儲,最終匯入指標(biāo)、報(bào)表和數(shù)據(jù)服務(wù)系統(tǒng)。數(shù)據(jù)血緣描述了數(shù)據(jù)的來源和去向,以及數(shù)據(jù)在多個(gè)處理過程中的轉(zhuǎn)換,是組織內(nèi)使數(shù)據(jù)發(fā)揮價(jià)值的重要基礎(chǔ)能力。

          數(shù)據(jù)地圖平臺在 2021 年接入了全鏈路核心元數(shù)據(jù),包括但不限于:Hive、Clickhouse、Kafka、BI 報(bào)表、BI 數(shù)據(jù)集、畫像、埋點(diǎn)、MySQL、Abase。這些數(shù)據(jù)全部要通過數(shù)據(jù)血緣連接起來,進(jìn)而可以進(jìn)行影響分析、內(nèi)部審計(jì)、SLA 保障、歸因分析、理解和查找數(shù)據(jù)、自動(dòng)化推薦等操作。

          隨著內(nèi)部數(shù)據(jù)不斷膨脹,簡單的數(shù)據(jù)血緣圖譜已經(jīng)無法滿足萬級表血緣的關(guān)系展示。一些突出的問題包括看不清單個(gè)表的直接上下游,看不清數(shù)據(jù)鏈路,整體情況等等。因此需要重構(gòu)一種更清晰、靈活、便利的方式。下圖簡單展示了優(yōu)化后的使用效果。

          在新版血緣圖譜中,我們可以直接清晰的看到每個(gè)表的多層上下游依賴關(guān)系,甚至可以直接看到一些特殊場景下用戶關(guān)注的表屬性,通過點(diǎn)擊節(jié)點(diǎn)高亮查看數(shù)據(jù)鏈路,更可以看清每層的統(tǒng)計(jì)信息。在下文中我們將詳細(xì)拆解優(yōu)化的全過程。

          需求發(fā)現(xiàn)

          要做出一個(gè)能滿足用戶需求的圖產(chǎn)品,首先是要清楚用戶想從圖中獲取什么信息,從而有針對性的將這些信息展示出來。從血緣圖譜的背景本身可以推斷出用戶希望在圖譜中查看表之間的關(guān)系,查看關(guān)系鏈路,而更多的使用場景待發(fā)掘。因此我們對內(nèi)部重度用戶進(jìn)行了訪談,整理得出了以下不同用戶角色使用數(shù)據(jù)血緣圖譜的用戶場景。

          結(jié)合訪談結(jié)果和用戶的日常反饋,數(shù)據(jù)血緣圖譜的場景按目前用戶的使用頻率從大到小排序依次為:

          場景

          用戶關(guān)注

          場景描述

          影響分析

          下游

          當(dāng)處于血緣上游的研發(fā)同學(xué)修改任務(wù)前,通過查看自己的下游,通知對應(yīng)資產(chǎn)或任務(wù)的負(fù)責(zé)人,進(jìn)行相應(yīng)的修改,否則會造成嚴(yán)重的生產(chǎn)事故。

          找數(shù)理解數(shù)


          上游

          在找數(shù)據(jù)時(shí),通過查看一份數(shù)據(jù)資產(chǎn)的血緣,來更多的了解它的“前世今生”,可以更好的判定當(dāng)前資產(chǎn)是不是自己需要的,或者是不是值得信賴的。就像了解一個(gè)人,可以從他周圍的朋友中得到很多信息一樣,是對這個(gè)人“生平”很好的補(bǔ)充。

          鏈路梳理

          鏈路

          事先挑選已知的核心任務(wù),通過血緣關(guān)系,自動(dòng)化的梳理出其所在的核心鏈路。多用于內(nèi)審和數(shù)據(jù)治理。

          歸因分析

          上游

          當(dāng)某一個(gè)指標(biāo)或字段數(shù)據(jù)/產(chǎn)出時(shí)間等出問題時(shí),通過查看血緣上游的任務(wù)或資產(chǎn),排查出造成問題的根因。

          使用分析

          下游

          一個(gè)表的下游表越多,使用越頻繁,可以認(rèn)為價(jià)值越大。

          抽象出幾個(gè)主要需求即為:

          1. 表血緣關(guān)系查看:能從圖中清楚的瀏覽用戶關(guān)注的表的上下游血緣關(guān)系,最好還能便捷的查看一些場景相關(guān)的表屬性。
          2. 表血緣鏈路查看能清晰的查看到某個(gè)上游/下游表到用戶關(guān)注表的鏈路情況。
          3. 按關(guān)鍵指標(biāo)分組查看例如當(dāng)表數(shù)據(jù)發(fā)生變更時(shí),分組查看所有下游表的負(fù)責(zé)人以便通知變更。
          4. 篩選關(guān)鍵信息查看:例如用戶找數(shù)據(jù)指標(biāo)的時(shí)候,僅看相關(guān)的報(bào)表更高效。

          問題分析

          其實(shí)上述需求舊版血緣圖譜都有一定程度上的滿足,我們需要去找出舊版血緣圖譜提供的功能為什么不滿足用戶需求,有哪些問題需要在新版中注意避免。

          • 概覽:在數(shù)據(jù)量較小的情況下可用,在數(shù)據(jù)量大的時(shí)候完全不可用??床磺迕繉佑卸嗌賯€(gè)節(jié)點(diǎn),層級關(guān)系是怎么樣的,且鏈路查看困難。

          節(jié)點(diǎn)較少,比較清晰

          大量節(jié)點(diǎn),查看困難

          • 舊版血緣圖譜中功能細(xì)節(jié)粗糙:
            • 用戶無法直觀的區(qū)分節(jié)點(diǎn):舊版節(jié)點(diǎn)上顯示了表類型、庫名、表名。因此表名只能顯示幾個(gè)字符,不具備辨識度。
            • 無法知曉表到表之間的任務(wù):舊版血緣圖譜僅在側(cè)邊欄列出了與當(dāng)前表相關(guān)的任務(wù)有哪些并未列出加工邏輯的對應(yīng)關(guān)系,歸因分析困難。
            • 分組結(jié)構(gòu)不清晰:舊版是在原圖中框出節(jié)點(diǎn)來展示分組的。一方面是空間利用率更低,另一方面是看節(jié)點(diǎn)時(shí)難定位到所屬分組,看分組時(shí)則無法看清包含的節(jié)點(diǎn)。
            • 篩選功能不直觀:符合篩選條件的節(jié)點(diǎn)高亮展示,而被篩掉的表仍在圖中,無法有效提升用戶瀏覽效率。

          方案設(shè)計(jì)

          用戶在使用過程中看重的是查看關(guān)系的效率屬性的完備度,因此在設(shè)計(jì)優(yōu)化方案時(shí)會盡量從這兩點(diǎn)出發(fā)去考慮。

          首先是表數(shù)據(jù)查看的效率問題??床磺灞砻?,無法區(qū)分相同前綴的表是用戶痛點(diǎn)之一。首先我們統(tǒng)計(jì)了現(xiàn)有表的平均字符數(shù)是 47 位,于是調(diào)寬了節(jié)點(diǎn)讓用戶能更直觀的區(qū)分表名。用數(shù)據(jù)地圖平臺中通用的類型圖表來代替色塊圖例,讓數(shù)據(jù)類型一目了然。

          其次對于數(shù)據(jù)量大時(shí)看不清數(shù)據(jù)關(guān)系的問題,我們需要一個(gè)更緊湊清晰的數(shù)據(jù)呈現(xiàn)方式。通過需求分析和用戶調(diào)研,我們了解到用戶關(guān)心的是節(jié)點(diǎn)所在層級和節(jié)點(diǎn)之間的聯(lián)系。對于同一層級節(jié)點(diǎn)的先后順序,層級節(jié)點(diǎn)之間的關(guān)系不是很看重。

          說到緊湊的布局方式,自然而然我們就想到了列表。如果能用一個(gè)列表來承載層級血緣的節(jié)點(diǎn),用連線來連接不同層級的節(jié)點(diǎn),那么久可以表達(dá)節(jié)點(diǎn)之間的血緣關(guān)系了。當(dāng)節(jié)點(diǎn)較多超出一屏?xí)r可以拖動(dòng)此列滾動(dòng)條來查看更多節(jié)點(diǎn),連線隨之刷新位置。當(dāng)層級不滿一屏?xí)r整體居中展示,層級過多超過一屏?xí)r可以左右滑動(dòng)查看。這樣在保留層級結(jié)構(gòu)信息的同時(shí)最大程度的利用了可視區(qū)域,展示出了盡可能多的數(shù)據(jù)。

          新版血緣圖譜支持了點(diǎn)擊任意節(jié)點(diǎn)則高亮該節(jié)點(diǎn)到主節(jié)點(diǎn)的鏈路功能。配合列滾動(dòng)和連線刷新,不管數(shù)據(jù)量多大總能看清一整條數(shù)據(jù)鏈路。

          我們還在每列列表頂部增加了層級信息和節(jié)點(diǎn)統(tǒng)計(jì),讓用戶能同時(shí)查看每個(gè)節(jié)點(diǎn)細(xì)節(jié)和節(jié)點(diǎn)的整體分布。最終實(shí)現(xiàn)效果如下圖:

          當(dāng)用戶想去找數(shù),理解數(shù)或做歸因分析時(shí),不僅要了解一個(gè)表的上游依賴,更需要理解表的加工邏輯。因此我們在節(jié)點(diǎn)的連線上新增了任務(wù)信息。當(dāng)用戶 hover 到連線上后,連線會加粗高亮并彈出任務(wù)信息。我們還附上了大數(shù)據(jù)開發(fā)平臺的對應(yīng)任務(wù)鏈接,點(diǎn)擊鏈接即可跳轉(zhuǎn)到新頁面查看任務(wù)邏輯詳情。

          在設(shè)計(jì)分組功能時(shí),采用了每列獨(dú)立分組的方式。一般認(rèn)為用戶會關(guān)注有對應(yīng)分組數(shù)據(jù)的節(jié)點(diǎn),因此總將有分組的數(shù)據(jù)放在上面,無分組數(shù)據(jù)的置底,這樣排序能提升用戶的瀏覽效率。

          舊版血緣圖譜的篩選功能是在前端處理的,由于一些性能限制導(dǎo)致篩選后只能顯示部分?jǐn)?shù)據(jù),用戶無法得知符合條件的節(jié)點(diǎn)是否已經(jīng)全部展示。新版血緣圖譜針對這個(gè)用戶痛點(diǎn),將前端篩選改為了服務(wù)端篩選,盡量展示全符合要求的數(shù)據(jù)。每個(gè)層級的頂欄對應(yīng)更新為篩選后的統(tǒng)計(jì)信息。同時(shí)更新連線,如果篩選后節(jié)點(diǎn)之間是有關(guān)聯(lián)的,也會展示關(guān)聯(lián)關(guān)系和高亮關(guān)系鏈路。

          不同職能的用戶在不同場景下使用血緣圖譜時(shí)關(guān)注的節(jié)點(diǎn)屬性并不相同,如果血緣圖譜可以直接在圖上顯示用戶當(dāng)前想關(guān)注的表屬性就能幫助用戶更高效的解決問題。于是我們在血緣圖譜上設(shè)計(jì)了屬性展示功能,用戶可以勾選自己感興趣的屬性直接顯示到圖中。比如下圖中展示了每個(gè)節(jié)點(diǎn)表熱度和生命周期兩個(gè)屬性。

          技術(shù)實(shí)現(xiàn)

          技術(shù)選型

          在編碼實(shí)現(xiàn)之前,我們需要進(jìn)行技術(shù)選型。好的選型往往能讓編碼事半功倍。在做技術(shù)選型時(shí),我們會主要考慮實(shí)現(xiàn)復(fù)雜度、研發(fā)周期、可擴(kuò)展性三個(gè)角度。分析整個(gè)血緣圖譜的需求:

          1. Canvas 實(shí)現(xiàn)滾動(dòng)條,節(jié)點(diǎn)文字標(biāo)簽混排很復(fù)雜,要達(dá)到 HTML 的美觀度需要大量調(diào)試,后續(xù)迭代要新增屬性標(biāo)簽,進(jìn)行流式布局會很頭痛。開放組件給別的產(chǎn)品復(fù)用也有很大的定制成本。而這些問題使用 React 框架渲染就可以輕松解決。
          2. 如果用 DOM 實(shí)現(xiàn)不但很難實(shí)現(xiàn)箭頭,在連線高亮?xí)r也很難靈活處理層疊關(guān)系。在大數(shù)據(jù)量下連線很多,還容易出現(xiàn)性能問題。而這是 Canvas 的優(yōu)勢。

          于是我們結(jié)合兩者之長,選用了 React + Canvas 的混合模式來實(shí)現(xiàn)血緣圖譜。Canvas 居于底部,僅負(fù)責(zé)畫連線。React 在上層負(fù)責(zé)渲染節(jié)點(diǎn)響應(yīng) hover 等交互。DOM 層疊關(guān)系如下:

          整個(gè)血緣圖譜的初始化流程如下:

          • 數(shù)據(jù)預(yù)處理服務(wù)端給到點(diǎn)邊結(jié)構(gòu)的數(shù)據(jù)。由于兩個(gè)節(jié)點(diǎn)之間可能存在多個(gè)任務(wù),對應(yīng)會有多條連線記錄。而血緣圖譜中相同兩個(gè)節(jié)點(diǎn)之間僅一條連線,對應(yīng)多個(gè)任務(wù)。先做連線的合并處理。
          • 計(jì)算節(jié)點(diǎn)層級服務(wù)端會給到點(diǎn)邊結(jié)構(gòu)的數(shù)據(jù),根據(jù)主節(jié)點(diǎn)的連線關(guān)系向來源和去向兩個(gè)方向做廣度遍歷來確定每個(gè)節(jié)點(diǎn)的層級。
          • 數(shù)據(jù)分組按分組條件對每列數(shù)據(jù)進(jìn)行分組計(jì)算。
          • 節(jié)點(diǎn)布局根據(jù)層級和分組情況布局節(jié)點(diǎn),相對應(yīng)的每個(gè)節(jié)點(diǎn)有 { x, y, width, height 屬性以確定每個(gè)節(jié)點(diǎn)的定位。
          • 初始化畫布畫布用于繪制連線,響應(yīng)連線的交互。采用內(nèi)部自研的圖形渲染引擎實(shí)現(xiàn)。
          • 渲染節(jié)點(diǎn)根據(jù)節(jié)點(diǎn)的位置和分組情況用 React 渲染出每一列節(jié)點(diǎn) DOM。
          • 渲染畫布根據(jù)前景的列和節(jié)點(diǎn)位置調(diào)整畫布,繪制連線。在渲染連線時(shí)分兩個(gè)圖層:默認(rèn)狀態(tài)連線在底層;高亮鏈路和高亮連線狀態(tài)下的連線在上層。這樣做的好處是高亮的連線永遠(yuǎn)在默認(rèn)狀態(tài)的上方,不用特殊處理圖形的層疊關(guān)系。

          實(shí)現(xiàn)細(xì)節(jié)

          用這種混合模式的一個(gè)挑戰(zhàn)就是 Canvas 和 DOM 的刷新率和同步率。在血緣圖譜中滾動(dòng)橫向滾動(dòng)條和每一列的縱向滾動(dòng)條時(shí) Canvas 要進(jìn)行及時(shí)的刷新以保證連線和節(jié)點(diǎn)的相對位置一定。

          • 當(dāng)圖譜橫向滾動(dòng)時(shí),每條連線的斜率不變,只是端點(diǎn)左右平移了。我們可以通過更新繪圖矩陣來加速這種情況下的更新,不需要去重計(jì)算每條連線的位置。具體做法是監(jiān)聽容器的滾動(dòng)事件,根據(jù)容器的 scrollLeft 屬性來更新繪圖矩陣后重繪。
          • 當(dāng)圖譜縱向滾動(dòng)時(shí),與當(dāng)前滾動(dòng)的列中節(jié)點(diǎn)相連的連線斜率和端點(diǎn)都有變化,而與滾動(dòng)列不直接相連的連線無需更新。我們僅重計(jì)算并更新與當(dāng)前列連接的線條位置。

          另一個(gè)挑戰(zhàn)是 DOM 節(jié)點(diǎn)在大數(shù)據(jù)量下的性能問題。通常情況下我們認(rèn)為 Canvas 在大數(shù)據(jù)量渲染有更好的性能,而萬級的 DOM 節(jié)點(diǎn)就會讓用戶在使用中感受到卡頓了。這時(shí)候我們想到了按需渲染。 用戶在圖譜可視區(qū)域中一屏能看到的節(jié)點(diǎn)數(shù)量是有限的,高度為 1120 的容器中,一列僅存在至多 30 個(gè)節(jié)點(diǎn)。如果僅渲染可見的節(jié)點(diǎn),則能保證使用過程的流暢。具體做法是在節(jié)點(diǎn)布局時(shí)增加以下步驟:

          • 根據(jù)視口的位置(主要是圖容器的橫向滾動(dòng)距離 scrollLeft )和每一列的滾動(dòng)距離(主要是每一列容器的縱向滾動(dòng)距離 scrollTop )計(jì)算目前的可視范圍。
          • 計(jì)算節(jié)點(diǎn)坐標(biāo)時(shí)判斷是否在可視范圍的上半屏和下半屏內(nèi),如果在此范圍內(nèi)則打標(biāo)。多顯示一屏的節(jié)點(diǎn)是希望在用戶上下滾動(dòng)瀏覽節(jié)點(diǎn)時(shí)不會出現(xiàn)空白區(qū)域閃一下等體驗(yàn)不佳的問題。
          • 計(jì)算出每一列的真實(shí)長度。

          在 React 渲染時(shí)更新每列容器的長度,將節(jié)點(diǎn)根據(jù)坐標(biāo)絕對定位到正確的位置上??雌饋砭透夸秩镜男Ч恢?,渲染效率大幅提升。

          然而問題并不止于此。在進(jìn)行大數(shù)據(jù)量的縱向滾動(dòng)時(shí),會發(fā)現(xiàn)幀率很低,交互還是不流暢。分析得知是由于列表滾動(dòng)時(shí)會在短時(shí)間內(nèi)進(jìn)行大量線條重計(jì)算和渲染。于是還要在 Canvas 繪制上進(jìn)行優(yōu)化。

          我們從上圖可以看到在單層節(jié)點(diǎn)很多的情況下,主節(jié)點(diǎn)與不可見節(jié)點(diǎn)的連線可見,但是沒有任何價(jià)值,只是加重了用戶對當(dāng)前節(jié)點(diǎn)連線查看的負(fù)擔(dān)。因此我們對線條也進(jìn)行了渲染優(yōu)化,僅當(dāng)一條連線兩端的節(jié)點(diǎn)都在可見范圍中時(shí)才渲染連線,在連線的 Tooltip 上增加了來源去向的展示輔助查看。至此我們做到了在復(fù)雜情況下的流暢展示血緣數(shù)據(jù)。


          總結(jié)

          以上就是數(shù)據(jù)血緣圖譜的整個(gè)優(yōu)化過程。在這個(gè)過程中,我總結(jié)起來就是在了解用戶訴求的前提下,克制地表達(dá)關(guān)系圖中的信息,在合適的場景下突出核心的內(nèi)容。做圖分析產(chǎn)品時(shí)不需要拘泥于某種形式,而是真正的從用戶需求出發(fā),為用戶服務(wù)。

          關(guān)于我們

          火山引擎大數(shù)據(jù)研發(fā)治理套件 DataLeap

          一站式數(shù)據(jù)中臺套件,幫助用戶快速完成數(shù)據(jù)集成、開發(fā)、運(yùn)維、治理、資產(chǎn)、安全等全套數(shù)據(jù)中臺建設(shè),幫助數(shù)據(jù)團(tuán)隊(duì)有效的降低工作成本和數(shù)據(jù)維護(hù)成本、挖掘數(shù)據(jù)價(jià)值、為企業(yè)決策提供數(shù)據(jù)支撐。

          歡迎加入字節(jié)跳動(dòng)數(shù)據(jù)平臺官方群,進(jìn)行數(shù)據(jù)技術(shù)交流、獲取更多內(nèi)容干貨

          點(diǎn)擊 大數(shù)據(jù)研發(fā)治理套件-火山引擎 了解產(chǎn)品詳情


          主站蜘蛛池模板: 国产亚洲福利一区二区免费看| 日本欧洲视频一区| 武侠古典一区二区三区中文| 日本一区二区三区高清| 国产在线不卡一区| 亚洲无码一区二区三区| 91一区二区在线观看精品| 一区二区精品在线| 欧洲亚洲综合一区二区三区| 国产成人欧美一区二区三区| 一区二区三区www| 亚洲中文字幕一区精品自拍| 韩国一区二区三区| 91精品国产一区二区三区左线| 制服丝袜一区在线| 国产一区二区在线视频| 在线不卡一区二区三区日韩| 国产色情一区二区三区在线播放| 亚洲欧洲一区二区| 国产色综合一区二区三区| 久久久久久人妻一区二区三区| 美女视频一区二区| 久久久久人妻一区精品色 | 日韩美一区二区三区| 国产品无码一区二区三区在线蜜桃| 亚洲一区二区三区在线观看网站| 中文字幕在线播放一区| 国产小仙女视频一区二区三区| 一区二区三区中文字幕| 加勒比精品久久一区二区三区| 亚州AV综合色区无码一区| 一区二区三区在线|欧| 精品乱人伦一区二区三区| 亚洲国产一区视频| 国内偷窥一区二区三区视频| 日本不卡一区二区三区| 亚洲av无码一区二区三区不卡 | 无码国产精品一区二区免费 | 久久一区二区三区精品| 污污内射在线观看一区二区少妇| 久久久久一区二区三区|