【D3.js in Action 3 精譯】1.2.2 可縮放矢量圖形(三)

當前內容所在位置

  • 第一部分 D3.js 基礎知識
    • 第一章 D3.js 簡介
      • 1.1 何為 D3.js?
      • 1.2 D3 生態系統——入門須知
        • 1.2.1 HTML 與 DOM
        • 1.2.2 SVG - 可縮放矢量圖形 ??
          • 第一部分
          • 第二部分
          • 【第三部分】??
        • 1.2.3 Canvas 與 WebGL(精譯中 ?)
        • 1.2.4 CSS(待翻譯)
        • 1.2.5 JavaScript(待翻譯)
        • 1.2.6 Node 與 JavaScript 框架(待翻譯)
        • 1.2.7 Observable 記事本(待翻譯)

譯注
(上接 1.2.2 小節(二))
…… 關于 SVG 描邊(strokes)的位置

當對齊可視化項目中的圖形時,需要特別注意:SVG 圖形繪制出的描邊是在內外邊界上平均展布的。如下圖所示,已知一個 width 屬性為 40px 的矩形,令 stroke-width 的值為 1,則在視覺效果上會在矩形的左右兩邊各增加寬度為 0.5px 的描邊(而不是下意識地以為的那樣在各邊均增加 1px),最終實際的總寬度為 41px;若令 stroke-width 的值為 2,則左右兩邊各增加 1px,以此類推。

描邊寬度 stroke-width 對 SVG 圖形實際寬度的影響描邊寬度 stroke-width 對 SVG 圖形實際寬度的影響

(……關于 SVG 描邊(strokes)的位置)

5 圓與橢圓

在數據可視化中常常會用到圓形。它們天然吸引眼球,使可視化效果看起來更友好、更有趣。SVG 的圓是通過 <circle /> 元素繪制的,其必選屬性包括圓心位置(cx, cy)與半徑(r),如圖 1.17 所示。圓的半徑是從圓心到圓周上任意一點繪制的線的長度。將以下圓形添加到示例中,令圓心位于 (530, 80) 處,且半徑為 50px

<circle cx="530" cy="80" r="50" />

圖 1.17
圖 1.17 在 SVG 容器的坐標系中定位圓和橢圓并調整其大小

還可以為圓設置填充(fill)與描邊(stroke)屬性(attribute)。要生成圖 1.17 中的圓,令填充色為透明(transparent)、描邊寬度為 3px、描邊顏色為 #81c21c(譯注:這里應該參考的是最終效果圖 1.8,圖 1.17 只是示意圖)。

同理,<ellipse /> 元素必須指定圓心坐標(cx, cy),但不像圓有固定半徑,橢圓的半徑會變化,使其呈扁平狀——這是通過聲明橢圓的水平半徑(rx)和垂直半徑(ry)來實現的。將如下代碼片段添加到示例中,將在圓的下方繪制一個橢圓,其水平半徑為 50px、垂直半徑為 30px

<ellipse cx="530" cy="205" rx="50" ry="30" />
6 路徑

SVG 的路徑(path)元素是目前為止所有 SVG 元素中最靈活的一種。在 D3 中,路徑被廣泛用于繪制幾乎所有的復雜形狀和曲線。這些形狀和曲線是無法用目前討論過的圖形基元(線、矩形、圓和橢圓)來表示的。

路徑元素通過聲明 d 屬性(這里的“d”代表“draw”,即“繪制”)來指示瀏覽器進行繪制。d 屬性包含一系列命令:從開始繪制路徑的位置,到使用的一系列曲線類型,一直到確定該路徑是否為一個封閉圖形為止。例如,在圖形畫廊示例中添加以下路徑元素:

<path d="M680 150 C 710 80, 725 80, 755 150 S 810 220, 840 150" fill="none" stroke="#773b9a" stroke-width="3" />

如圖 1.18 所示, d 屬性以 M680 150 開頭,表示“移動(M)到坐標(680,150)處”。接著從起點坐標(680 150)到 d 屬性最后一個坐標(840 150)所指定的終點,繪制一條三階貝塞爾曲線(cubic Bézier curve)。三階貝塞爾曲線還需要設置控制點來定義曲線的陡峭程度和彎曲方向。這些控制點從字母 C(這里的“C”代表“cubic curve”,即“三次方曲線”)之后開始,直到字母 S(這里的“S”代表“stop”,即“停止”)之后結束。

圖 1.18 一條簡單的 SVG 路徑及其控制點
圖 1.18 一條簡單的 SVG 路徑及其控制點

注意

如需深入了解 SVG 路徑,請參閱 MDN 的教程:https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths。

手動設置 d 屬性僅適用于簡單的圖形,隨著圖形復雜度增加,純手動編寫將會變得非常繁瑣。所幸 D3 提供了強大的圖形生成工具來專門處理 d 屬性的計算。本書第 4 章將深入討論。

路徑還有一個需要牢記的重要知識點:無論路徑元素是否閉合,只要其 fill 屬性值不為 nonetransparent,瀏覽器就會默認填充為黑色,如本例所示。

7 文本

內聯 SVG 圖形的最大優勢之一在于支持屏幕閱讀器訪問其包含的文本內容。這對于可訪問性而言是一大優勢。由于數據可視化通常包含多個標簽,因此有必要了解如何使用 <text> 元素來操作 SVG 文本。通過往示例中添加標簽可以了解 SVG 文本的基本工作原理。

目前為止我們討論的 SVG 圖形都使用了自閉合標簽(如 <line /><rect /><path /> ……)。在使用 SVG 的 <text> 元素時,需要同時使用開標簽和閉標簽,并將待顯示文本放置在這兩個標簽之間。例如,添加一個內容為“line”的文本元素:

<text>line</text>

保存并重新加載頁面。您可能以為文本會出現在 SVG 容器的左上角,但卻看不到……這是為什么呢?默認情況下,SVG 文本的位置是參照其基線計算得來的,通過 dominant-baseline 屬性控制。如果文本基線的坐標是 (0, 0),如圖 1.19 所示,實際文本最終將位于 SVG 容器之外。由于任何位于 SVG 容器之外的元素都是不可見的,所以看不到文本。

圖 1.19 在 SVG 容器外定位文本
圖 1.19 在 SVG 容器外定位文本

在使用 SVG 文本元素時,另一個需要考慮的問題是文本如何流動(flow)。常規 HTML 元素在頁面上的位置是按照控制內容流動的特定規則來確定的。如果在頁面中插入大量 <div> 元素,它們會自然地堆疊在一起,其內容也會回流(reflow),不會超出容器的范圍;而 SVG 文本根本不會流動,開發人員必須單獨設置每個文本元素的 xy 屬性。例如通過它們將文本放在坐標點 (60, 260) 處,標簽“line”才會出現在圖形畫廊示例中 SVG 直線段的下方:

<text x="60" y="260">line</text>

作為練習,再創建一個新的文本元素,并將標簽“rect”置于矩形和正方形的下方。

至此,我們通過 xy 屬性聲明了文本元素 左下角 的位置。怎樣設置文本中點位置呢?通過屬性 text-anchor 來實現:令其值為 middle 即可,如圖 1.20 所示。再比如,利用該屬性還可以將圓形的文本標簽居中。

<text x="530" y="155" text-anchor="middle">circle</text>

圖 1.20圖 1.20 text-anchor 屬性對 SVG 文本對齊方式的影響。默認值為 start;根據其中間位置對齊,值為 middle;設置末尾對齊,值為 end

最后,分別為橢圓和路徑元素各添加一個文本標簽。SVG 文本默認為黑色,可以通過 fill 屬性(attribute)進行更改。

8 分組元素

本小節要討論的最后一個 SVG 元素為分組元素(group element)。分組元素(即 <g> 元素)與之前討論過的其他 SVG 元素有所不同。它既沒有視覺上的圖形表示,也不存在具有邊界的空間;相反,它是 SVG 各元素的邏輯分組,廣泛應用于由多個圖形和標簽組成的可視化效果中。

如果希望正方形標簽和“rect”文本標簽一同顯示,并在 SVG 容器中整體平移,可以如以下示例將它們放到一個 <g> 元素中。注意,<rect> 元素的左上角已變為了坐標原點 (0, 0)<text> 位于 (0, 85) 處,保持在 <rect> 的下方:

<g><rect x="0" y="0" width="60" height="60" /><text x="0" y="85">rect</text>
</g>

此時,包含正方形及其文本標簽的組出現在了 SVG 容器的左上角。我們可以在 SVG 容器中任意移動這個組及其包含的所有元素,始終保持正方形與文本標簽之間的對齊方式不變。

使用 transform 屬性可以在 SVG 容器中平移該分組。transform 屬性比之前學過的其他屬性略顯復雜,但與 CSS 中 transform 屬性的用法相同。它接受一個或一系列變換(transformation,如平移、旋轉、縮放等)作為屬性值。平移一個分組使用 translate(x, y) 變換。如果要將 <rect><text> 元素移回原位,需要令分組元素右移 260px 并下移 175px,即令 <g> 元素 transform 屬性的值為 transform="translate(260,175)"

<g transform="translate(260,175)"><rect x="0" y="0" width="60" height="60" /><text x="0" y="85">rect</text>
</g>

<g> 元素的另一個特點,是其子元素可以繼承它的樣式屬性(styling attributes)。下面舉例說明。由于前面“rect”文本標簽已經和正方形歸為同一組,故先將其余文本元簽統一放到另一個 <g> 元素內:

<g><text x="60" y="260">line</text><text x="530" y="155" style="text-anchor:middle">circle</text><text x="530" y="260" style="text-anchor:middle">ellipse</text><text x="730" y="260">path</text>
</g>

如果令 <g>fill 屬性值為 #636466,則里面的每個 <text> 元素都將繼承相同的顏色;同理,如果添加的是 font-familyfont-size 屬性,同一組內的文本元素也將繼承這些樣式屬性(properties)。

<g fill="#636466" style="font-size:16px; font-family:monospace"><text x="60" y="260">line</text><text x="530" y="155" style="text-anchor:middle">circle</text><text x="530" y="260" style="text-anchor:middle">ellipse</text><text x="730" y="260">path</text>
</g>

最后一次再重新加載頁面,注意觀察分組內的標簽繼承的顏色和字體效果;再看看分組外的標簽是否保持原來的外觀不變。像這樣在分組元素上應用共享樣式的做法非常方便,可以幫助您在工作中遵循 DRY(即 Don’t Repeat Yourself,不要重復自己)原則。需要更新屬性時,在分組容器上操作也會很簡單。

恭喜您完成了本書的第一個練習!您可以在代碼清單 1.2 及源碼文件的 end 文件夾找到 SVG 圖形畫廊的完整代碼。在構建首個 D3 項目時,該練習可以作為參考。

代碼清單 1.2 SVG 圖形畫廊示例的完整 HTML 代碼

<!DOCTYPE html>
<html>
<head> <!-- [略] --> </head>
<body><div style="width:100%; max-width:1200px; margin:0 auto;"><svg viewBox="0 0 900 300" style="border:1px solid black;"><line x1="50" y1="45" x2="140" y2="225" stroke="black" /><rect x="260" y="25" width="120" height="60" fill="#6ba5d7" /><rect x="260" y="100" width="120" height="60" rx="20" ry="20" fill="#6ba5d7" /> <g transform="translate(260, 175)"><rect x="0" y="0" width="60" height="60" fill="transparent"  stroke="#6ba5d7" /><text x="0" y="85">rect</text></g><circle cx="530" cy="80" r="50" fill="none" stroke="#81c21c" stroke- width="3" /><ellipse cx="530" cy="205" rx="50" ry="30" fill="#81c21c" /><path d="M680 150 C 710 80, 725 80, 755 150 S 810 220, 840 150" fill="none" stroke="#773b9a" stroke-width="3" /><g fill="#636466" style="font-size:16px; font-family:monospace"><text x="60" y="260">line</text><text x="530" y="155" style="text-anchor:middle">circle</text><text x="530" y="260" style="text-anchor:middle">ellipse</text><text x="730" y="260">path</text></g></svg></div>
</body>
</html>

強化練習:創建 SVG 圖形

現在該您小試牛刀了——創建如下圖所示的 SVG 圖形。您可以在源碼文件夾 02_SVG_exercise/start 中進行操作。具體要求如下:

  • 創建一個響應式 SVG 容器,寬高均為 400px(屏幕上留足空間)。
  • 繪制一個寬高均為 200px 的正方形。將其置于 SVG 容器的中心位置,并指定透明色填充及 5px 的黑色描邊。
  • 在 SVG 容器的中心添加一個半徑為 100px 的圓。將其 fill 屬性設置為 CSS 顏色名稱“plum”。
  • 繪制兩條描邊為 5px 的黑色對角線:一條從正方形的左上角畫到右下角;另一條從正方形的右上角畫到左下角。
  • 在正方形上方添加文本“SVG is awesome!”字樣,并將其置于 SVG 容器的中心。其他文本樣式:字號 18px、無襯線字體。

SVG 強化練習項目效果圖
強烈建議通過練習該 SVG 圖形來強化本小節介紹的知識點

該練手項目的完整參考代碼,請參閱 附錄 DD.1.1 小節或隨書源碼文件中的 02_SVG_exercise/end 文件夾中。建議盡量獨立完成。

(SVG 基礎知識譯完了,內容有點多,再自己做個小結吧)

本節 SVG 基礎知識要點梳理
  • 圓(circle)與橢圓(ellipse):都具有圓心坐標(cx / cy)和半徑,只是橢圓的半徑有兩個(rxry),圓只有一個(r);圓其實是橢圓的 特殊情況
  • 路徑(path)是 SVG 圖形中最復雜的幾何基元,其屬性 d 包含一系列命令,可借助 D3 的生成工具代替純手工賦值;
  • 文本(text)——
    • 在 SVG 中不隨常規 HTML 內容流動;
    • 其位置是基于文本基線計算得來的,需要手動設置(xy);
    • 文本對齊通過 text-anchor 屬性調整,可選值:start | middle | end
  • 分組(g)元素——
    • 沒有視覺圖形表示,也不占據空間;
    • 放入同一分組的元素可整體移動;
    • 設置在 g 上的樣式可被子元素繼承:如 fillfont-sizefont-family 等;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/39496.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/39496.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/39496.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gameui C++的代碼

gameui C的代碼 #include <graphics.h> #include "gameboard.h" const int WIDTH 560; const int HEIGHT 780; const int GRID_SIZE 120; class GameUi { private: public:GameUi(GameBoard& gb) {// 初始化圖形窗口initgraph(WIDTH, HEIGHT);// 設置…

小米內推官

小米硬件提前批開始啦&#xff01;&#xff01;&#xff01;&#xff01; 請使用小米公司內推碼: Q9BN21S 招聘對象&#xff1a;25屆秋招 中國內地:畢業時間2025.01-2025.12 中國港澳臺及海外:畢業時間2025.07-2025.12 工作地點&#xff1a;北京、南京、武漢、深圳、上海等…

C++中Ranges庫的基本用法,如何簡化和增強對集合的操作。

Ranges庫的基本用法 什么是Ranges庫&#xff1f; C20引入的Ranges庫&#xff08;<ranges>&#xff09;是一個強大的工具集&#xff0c;旨在簡化和增強對集合&#xff08;如數組、向量等序列容器&#xff09;的操作。它提供了一套用于操作序列的功能性接口&#xff0c;使…

獨立站新風口:TikTok達人帶貨背后的雙贏合作之道

TikTok以其龐大的用戶基礎、高度互動性和創新的內容形式&#xff0c;為獨立站帶來了前所未有的發展機遇。獨立站與TikTok達人的合作&#xff0c;不僅能夠幫助獨立站快速提升品牌知名度和銷售額&#xff0c;還能為TikTok達人帶來更多商業機會和影響力。本文Nox聚星將和大家探討獨…

Android sdk 安裝已經環境配置

&#x1f34e;個人博客&#xff1a;個人主頁 &#x1f3c6;個人專欄&#xff1a;Android ?? 功不唐捐&#xff0c;玉汝于成 目錄 正文 一、下載 二、安裝 三、環境配置 我的其他博客 正文 一、下載 1、大家可去官網下載 因為需要魔法 所以就不展示了 2、去下面這…

經典shell運維實用腳本~

以下腳本可謂日常工作常用到的經典腳本案例。希望可以幫助大家提升提升自動化能力&#xff01; 1、監控100臺服務器磁盤利用率腳本 #!/bin/bashHOST_INFOhost.infofor IP in $(awk /^[^#]/{print $1} $HOST_INFO); do USER$(awk -v ip$IP ip$1{print $2} $HOST_INFO) P…

【JS】純web端使用ffmpeg實現的視頻編輯器-視頻合并

純前端實現的視頻合并 接上篇ffmpeg文章 【JS】純web端使用ffmpeg實現的視頻編輯器 這次主要添加了一個函數&#xff0c;實現了視頻合并的操作。 static mergeArgs(timelineList) {const cmd []console.log(時間軸數據,timelineList)console.log("文件1",this.readD…

常用目標檢測的格式轉換腳本文件txt,json等

常用目標檢測的格式轉換腳本文件txt,json等 文章目錄 常用目標檢測的格式轉換腳本文件txt,json等前言一、json格式轉yolo的txt格式二、yolov8的關鍵點labelme打的標簽json格式轉可訓練的txt格式三、yolo的目標檢測txt格式轉coco數據集標簽的json格式四、根據yolo的目標檢測訓練…

Vue+ElementUi實現錄音播放上傳及處理getUserMedia報錯問題

1.Vue安裝插件 npm install --registryhttps://registry.npmmirror.com 2.Vue頁面使用 <template><div class"app-container"><!-- header --><el-header class"procedureHeader" style"height: 20px;"><el-divid…

vue2 接口文檔

const assetmanagementIndex (params) > getAction("/asset/assetmanagementsystem/page", params); //資產管理制度表分頁列表 const assetmanagementPost (params) > postAction("/asset/assetmanagementsystem", params); //資產管理制度表新增…

維護Nginx千字經驗總結

Hello , 我是恒 。 維護putty和nginx兩個項目好久了&#xff0c;用面向底層的思路去接觸 在nginx社區的收獲不少&#xff0c;在這里談談我的感悟 Nginx的奪冠不是偶然 高速:一方面&#xff0c;在正常情況下&#xff0c;單次請求會得到更快的響應&#xff1b;另一方面&#xff0…

從零開始學量化~Ptrade使用教程——安裝與登錄

PTrade交易系統是一款高凈值和機構投資者專業投資軟件&#xff0c;為用戶提供普通交易、籃子交易、日內回轉交易、算法交易、量化投研/回測/實盤等各種交易工具&#xff0c;滿足用戶的各種交易需求和交易場景&#xff0c;幫助用戶提高交易效率。 運行環境及安裝 操作系統&…

昇思25天學習打卡營第3天 | 數據集 Dataset

數據是深度學習的基礎&#xff0c;高質量的數據輸入將在整個深度神經網絡中起到積極作用。MindSpore提供基于Pipeline的數據引擎&#xff0c;通過數據集&#xff08;Dataset&#xff09;和數據變換&#xff08;Transforms&#xff09;實現高效的數據預處理。其中Dataset是Pipel…

將數據切分成N份,采用NCCL異步通信,讓all_gather+matmul盡量Overlap

將數據切分成N份,采用NCCL異步通信,讓all_gathermatmul盡量Overlap 一.測試數據二.測試環境三.普通實現四.分塊實現 本文演示了如何將數據切分成N份,采用NCCL異步通信,讓all_gathermatmul盡量Overlap 一.測試數據 1.測試規模:8192*8192 world_size22.單算子:all_gather:0.035…

代理IP的10大誤區:區分事實與虛構

在當今的數字時代&#xff0c;代理已成為在線環境不可或缺的一部分。它們的用途廣泛&#xff0c;從增強在線隱私到繞過地理限制。然而&#xff0c;盡管代理無處不在&#xff0c;但仍存在許多圍繞代理的誤解。在本博客中&#xff0c;我們將探討和消除一些最常見的代理誤解&#…

人腦網絡的多層建模與分析

摘要 了解人類大腦的結構及其與功能的關系&#xff0c;對于各種應用至關重要&#xff0c;包括但不限于預防、處理和治療腦部疾病(如阿爾茨海默病或帕金森病)&#xff0c;以及精神疾病(如精神分裂癥)的新方法。結構和功能神經影像學方面的最新進展&#xff0c;以及計算機科學等…

OBS 免費的錄屏軟件

一、下載 obs 【OBS】OBS Studio 的安裝、參數設置和錄屏、攝像頭使用教程-CSDN博客 二、使用 obs & 輸出無黑屏 【OBS任意指定區域錄屏的方法-嗶哩嗶哩】 https://b23.tv/aM0hj8A OBS任意指定區域錄屏的方法_嗶哩嗶哩_bilibili 步驟&#xff1a; 1&#xff09;獲取區域…

012-GeoGebra基礎篇-構造圓的切線

前邊文章對于基礎內容已經悉數覆蓋了&#xff0c;這一篇我就不放具體的細節&#xff0c;若有需要可以復刻一下 目錄 一、成品展示二、算式內容三、正確性檢查五、文章最后 一、成品展示 二、算式內容 A(0,0) B(3,0) c: Circle(A,B) C(5,4) sSegment(A,C) DMidpoint(s) d: Circ…

k8s部署單節點redis

一、configmap # cat redis-configmap.yaml apiVersion: v1 kind: ConfigMap metadata:name: redis-single-confignamespace: redis data:redis.conf: |daemonize nobind 0.0.0.0port 6379tcp-backlog 511timeout 0tcp-keepalive 300pidfile /data/redis-server.pidlogfile /d…

全網小視頻去水印接口使用說明

一、請求地址&#xff1a; https://www.lytcreate.com/api/qsy/ 二、請求方式&#xff1a;POST 三、請求體&#xff1a;JSON body {"token": "個人中心的token","url": "視頻分享地址"} token獲取地址&#xff0c;訪問&#xff…