前端canvas項目實戰——簡歷制作網站(五):右側屬性欄(字體、字號、行間距)

目錄

  • 前言
  • 一、效果展示
  • 二、實現步驟
    • 1. 優化代碼,提取常量
    • 2. 實現3個編輯模塊
    • 3. 實現updateFontProperty方法
    • 4. 一個常見的用法:僅更新當前選中文字的樣式
  • 三、Show u the code
  • 后記

前言

上一篇博文中,我們擴充了線條對象(fabric.Line)的屬性列表,使用戶可以為畫布中選中的線條增加或修改端點樣式(多種剪頭、圓形、菱形等)。

這篇博文是《前端canvas項目實戰——簡歷制作網站》付費專欄系列博文的第五篇——右側屬性欄(字體、字號、行間距),主要的內容有:

  1. 針對文本框(fabric.Textbox)對象: 擴充屬性列表,使用戶可以修改畫布中選中的文本框的字體、字號和行間距。
  2. 在實現了整體更新文本框屬性的基礎上,還實現了僅更新用戶選中的部分文字的樣式。

如有需要,可以:

  • 點擊這里,返回第一篇《前端canvas項目實戰——簡歷制作網站(一)——左側工具欄》
  • 點擊這里,返回上一篇《前端canvas項目實戰——簡歷制作網站(四)——右側屬性欄(線條端點樣式)》

一、效果展示

  • 動手體驗
    CodeSandbox會自動對代碼進行編譯,并提供地址以供體驗代碼效果
    由于CSDN的鏈接跳轉有問題,會導致頁面無法工作,請復制以下鏈接在瀏覽器打開:
    https://cy37vt.csb.app/

  • 動態效果演示

  • 本節之后,我們的簡歷能做成什么樣子
    我們可以修改字體、字號和行間距了

二、實現步驟

作為簡歷,其中包含最多的就是文字。因此,文字的各種樣式至關重要,我們在本節初步實現字體、字號和行間距的編輯能力。

1. 優化代碼,提取常量

當我們實現越來越多的編輯模塊時,object-props.js文件越來越大。其中包含了很多我們為下拉菜單的菜單項設置的常量,這些常量不需要經常修改,但占據了很多行。為了避免這個文件過于龐大,以及做好ModalView的分離,我們將這些數據拆分到一個constants.js常量文件中。

const fontFamilyOptions = [{ key: "黑體", value: "SimHei", platform: "windows" },{ key: "黑體", value: "STHeitiSC-Light", platform: "mac" },..."Times New Roman","Georgia",...
];const fontSizeOptions = [{ key: "初號", value: 36 },{ key: "小初", value: 31 },...9,10,...
];const lineHeightOptions = [ 0, 2,4, ...
];export { fontFamilyOptions, fontSizeOptions, lineHeightOptions };

我們將本節新增定義的fontFamilyOptions, fontSizeOptionslineHeightOptions提取到了這個文件中,它們分別是字體字號行間距的可取值列表。

2. 實現3個編輯模塊

這里的3個編輯模塊的代碼邏輯大同小異,且互相獨立,各不影響。所以僅列出fontFamily字體屬性編輯模塊的實現。

  import { fontFamilyOptions } from "../../apis/constants";const isWindows = navigator.userAgent.toUpperCase().indexOf("WIN") !== -1;const isMac = navigator.userAgent.toUpperCase().indexOf("MAC") !== -1;const FontFamilyWrapper = (props) => {const optionFilter = (option) => {return (!option.hasOwnProperty("key") ||(option.platform === "windows" && isWindows) ||(option.platform === "mac" && isMac));};const menuItems = useMemo(() => {return fontFamilyOptions.filter(optionFilter).map((option, index) => {let _key = option, _value = option;if (option.hasOwnProperty("key")) {_key = option.key;_value = option.value;}return (<Option key={`font-family-${_key}`} value={_value} style={{ fontFamily: _value }}>{_key}</Option>);});});return (<div className="property-row" key={props.key}><span className="property-title">字體</span><div className="property-container"><Select value={fontFamily} bordered={false} style={{ width: "100%" }}onChange={(value) => canvasAPI.updateFontProperty("fontFamily", value)}>{menuItems}</Select></div></div>);};

由上述代碼可見,共分為4個部分,下面分別講解:

  1. 從常量文件constants.js中引入定義好的字體常量
  2. 由于同樣的字體在WindowsMac系統中的名稱不同,而我們的項目目前沒有后臺的支持,所以暫且區分不同系統來實現字體。這里在后續章節中開始實現后臺服務器時將會重構。
  3. 組裝下拉菜單的菜單項,這里與之前的章節類似。
  4. 繪制字體的下拉菜單,這里用戶選擇了不同的字體后,onChange事件調用canvasAPI.updateFontProperty方法去更新整個文本框的字體,讓每個字符都使用相同的字體

3. 實現updateFontProperty方法

  static updateFontProperty(key, newValue) {let { activeObject, canvas } = store.getState();ObjectAPI.updateProperty(activeObject, key, newValue);canvas.renderAll();}

這里的代碼很簡單,直接調用了updateProperty方法,去更新整個TextboxfontFamilyfontSizelineHeight等屬性。

updateProperty方法的實現在上一篇博文中有列出,這里不再贅述。如需回顧,可點擊前往

4. 一個常見的用法:僅更新當前選中文字的樣式

在目前的實現中,我們可以直接設置整個Textbox的屬性,這樣其中的所有字符都會設置為相同的屬性。但有時,我們會選中其中的部分文字,然后單獨更新它們的屬性。 這個時候就需要更加細致的實現來區分兩種情況。

首先確定目標,我們要實現的效果如下圖所示:

我們實現以下代碼在一個CanvasAPI.js文件中:

  // 1. 判斷是否對整個Textbox更新屬性static shouldUpdateTheWholeTextbox(object, key) {return !object?.isEditing || key === "lineHeight";}// 2. 更新Textbox的屬性static updateFontProperty(key, newValue) {let { activeObject, canvas } = store.getState();if (this.shouldUpdateTheWholeTextbox(activeObject, key)) {CanvasAPI._updateFontPropertyForWholeObject(key, newValue);} else {CanvasAPI._updateFontPropertyForSelection(key, newValue);}canvas.renderAll();}// 3. 更新整個Textbox的屬性static _updateFontPropertyForWholeObject(key, newValue) {let { activeObject } = store.getState();ObjectAPI.updateProperty(activeObject, key, newValue);}// 4. 更新Textbox中當前選中的部分文字的屬性static _updateFontPropertyForSelection(key, newValue) {let { activeObject, canvas } = store.getState();let style = {};style[key] = newValue;activeObject.setSelectionStyles(style);}

代碼邏輯比較清晰,共分為4個方法,下面分別解析:

1. shouldUpdateTheWholeTextbox方法: 判斷當前狀態下,應該整體更新文本框的屬性,還是僅更新選中的文字的屬性。邏輯上,處于非編輯態的文本框適用前者,否則適用后者。這里有一個特殊屬性lineHeight行間距。根據定義,這個屬性只能對整個文本框設置,不能僅對選中的文字設置。
2. updateFontProperty方法: 前文中實現過的方法,這里根據shouldUpdateTheWholeTextbox的返回值區分兩種狀態,調用不同的方法更新文本框屬性。
3. _updateFontPropertyForWholeObject方法: 更新整個文本框的屬性。
4. _updateFontPropertyForSelection方法: 僅更新文本框中當前選中的文字的屬性。


三、Show u the code

按照慣例,本節的完整代碼我也托管在了CodeSandbox中,點擊前往,查看完整代碼


后記

這篇博文中,我們實現了對文字的字體、字號和行間距的編輯。同時,根據我們日常的使用習慣,實現了對部分用戶選中的文字的屬性進行單獨地編輯。

作為簡歷中占據最大部分空間的文字對象,本章的實現很大程度上實現了用戶在制作簡歷時的核心需要。當然,這還遠遠不夠。在下一篇博文中,我們將實現設置文字的加粗、斜體、刪除線、下劃線等能力。

如有需要,可以:

  • 點擊這里,返回第一篇《前端canvas項目實戰——簡歷制作網站(一)——左側工具欄》
  • 點擊這里,返回上一篇《前端canvas項目實戰——簡歷制作網站(四)——右側屬性欄(線條端點樣式)》

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

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

相關文章

springboot 整合oauth2

1、EnableOAuth2Client&#xff1a;客戶端&#xff0c;提供OAuth2RestTemplate&#xff0c;用于客戶端訪問資源服務。 簡要步驟&#xff1a;客戶端訪問資源->客戶端發現沒有資源訪問token->客戶端根據授權類型生成跳轉url->瀏覽器 302 到認證授權服務進行認證、授權。…

Dockerfile構建過程詳解

Dockerfile介紹 docker是用來構建docker鏡像的文件&#xff01;命令參數腳本&#xff01; 構建步驟&#xff1a; 1、編寫一個dockerfile文件 2、docker build構建成為一個鏡像 3、docker run 運行鏡像 …

PDF轉Excel的未來:人工智能技術如何提升轉換效率和準確性

隨著信息技術的快速發展&#xff0c;PDF和Excel作為兩種重要的文件格式&#xff0c;在日常生活和工作中扮演著至關重要的角色。PDF以其獨特的跨平臺閱讀特性&#xff0c;成為了文件分享和傳輸的首選格式&#xff1b;而Excel則以其強大的數據處理能力&#xff0c;成為了數據分析…

【二分查找】【C++算法】378. 有序矩陣中第 K 小的元素

作者推薦 視頻算法專題 本文涉及的基礎知識點 二分查找算法合集 LeetCode378. 有序矩陣中第 K 小的元素 給你一個 n x n 矩陣 matrix &#xff0c;其中每行和每列元素均按升序排序&#xff0c;找到矩陣中第 k 小的元素。 請注意&#xff0c;它是 排序后 的第 k 小元素&…

機器人持續學習基準LIBERO系列10——文件結構

0.前置 機器人持續學習基準LIBERO系列1——基本介紹與安裝測試機器人持續學習基準LIBERO系列2——路徑與基準基本信息機器人持續學習基準LIBERO系列3——相機畫面可視化及單步移動更新機器人持續學習基準LIBERO系列4——robosuite最基本demo機器人持續學習基準LIBERO系列5——…

力扣日記3.3-【回溯算法篇】332. 重新安排行程

力扣日記&#xff1a;【回溯算法篇】332. 重新安排行程 日期&#xff1a;2023.3.3 參考&#xff1a;代碼隨想錄、力扣 ps&#xff1a;因為是困難題&#xff0c;望而卻步了一星期。。。T^T 332. 重新安排行程 題目描述 難度&#xff1a;困難 給你一份航線列表 tickets &#xf…

牛客小白月賽86

A-水鹽平衡_牛客小白月賽86 (nowcoder.com) #include<bits/stdc.h> #define endl \n #define int long long using namespace std; int a,b,c,d; void solve() {cin>>a>>b>>c>>d;if((double)a/b>(double)c/d) cout<<S<<endl;els…

關于脈沖負載應用中電阻器,您需要了解的 11 件事?

不幸的是&#xff0c;電阻器在脈沖負載下可能會失效。當脈沖功率耗散到器件的電阻元件時&#xff0c;它會產生熱量并增加電阻器的溫度。過熱會損壞電阻元件&#xff0c;導致電阻變化甚至設備開路。為了避免在設計中出現這種情況&#xff0c;以下是您在選擇元件時應了解的有關電…

excel統計分析——拉丁方設計

參考資料&#xff1a;生物統計學 拉丁方設計也是隨機區組設計&#xff0c;是對隨機區組設計的一種改進。它在行的方向和列的方向都可以看成區組&#xff0c;因此能實現雙向誤差的控制。在一般的試驗設計中&#xff0c;拉丁方常被看作雙區組設計&#xff0c;用于提高發現處理效應…

Skipped breakpoint at because it happened inside debugger evaluation親測可用

問題描述&#xff1a; 在多線程項目中&#xff0c;在idea中打斷點時&#xff0c;有時會遇到下面這種情況&#xff1a; idea左下角出現一行紅底或者綠底文字提示&#xff1a; Skipped breakpoint at because it happened inside debugger evaluation 然后我們能感受到的就是…

HTML中自定義鼠標右鍵菜單

今天突然有人跟我提到了HTML中如何自定義鼠標右鍵菜單&#xff0c;這里大概記錄一下吧&#xff0c;方便下次直接復制。免得還去看API文檔。 文章目錄 HTML中自定義鼠標右鍵菜單結果如下所示可以稍微改一下鼠標懸浮到右鍵菜單時的樣式結果如下所示 只在某個特定的div才可以顯示…

javascript 的eval()和with是干嘛的

原來JavaScript 中的eval() 和 with 是兩個強大的功能&#xff0c;但同時它們也具有潛在風險的特性&#xff0c;所以謹慎使用。 首先說說eval() 函數&#xff1a; 它接收一個字符串參數&#xff0c;并將其作為 JavaScript 代碼來解析和執行。 這意味著你可以使用 eval() 動態地…

《Scratch等級認證CCF-GESP真題解析》專欄總目錄

?? 專欄名稱:《Scratch等級認證CCF-GESP真題解析》 ?? 專欄介紹:中國計算機學會GESP《CCF編程能力等級認證》Scratch圖形化編程(1~4級)歷屆真題解析。 ?? 訂閱專欄:訂閱后可閱讀專欄內所有真題解析,真題持續更新中,限時9.9元,歡迎訂閱! Scratch圖形化編程一級 序…

2368. 受限條件下可到達節點的數目

2368. 受限條件下可到達節點的數目 題目鏈接&#xff1a;2368. 受限條件下可到達節點的數目 代碼如下&#xff1a; //深度優先遍歷 //參考&#xff1a;https://leetcode.cn/problems/reachable-nodes-with-restrictions/solutions/2662538/shu-shang-dfspythonjavacgojsrust-…

C++自學精簡實踐教程

一、介紹 1.1 教程特點 一篇文章從入門到就業有圖有真相&#xff0c;有測試用例&#xff0c;有作業&#xff1b;提供框架代碼&#xff0c;作業只需要代碼填空規范開發習慣&#xff0c;培養設計能力 1.2 參考書 唯一參考書《C Primer 第5版》?參考書下載&#xff1a; 藍奏云…

Acwing---3777. 磚塊

磚塊 1.題目2.基本思想3.代碼實現 1.題目 n 個磚塊排成一排&#xff0c;從左到右編號依次為 1~n。 每個磚塊要么是黑色的&#xff0c;要么是白色的。 現在你可以進行以下操作若干次&#xff08;可以是 0 次&#xff09;&#xff1a; 選擇兩個相鄰的磚塊&#xff0c;反轉它…

STL——stack

目錄 stack stack都有哪些接口 模擬實現一個stack stack 1. stack是一種容器適配器&#xff0c;專門用在具有后進先出操作的上下文環境中&#xff0c;其刪除只能從容器的一端進行元素的插入與提取操作。 2. stack是作為容器適配器被實現的&#xff0c;容器適配器即…

數據分析-Pandas數據的畫圖設置

數據分析-Pandas數據的畫圖設置 數據分析和處理中&#xff0c;難免會遇到各種數據&#xff0c;那么數據呈現怎樣的規律呢&#xff1f;不管金融數據&#xff0c;風控數據&#xff0c;營銷數據等等&#xff0c;莫不如此。如何通過圖示展示數據的規律&#xff1f; 數據表&#x…

春招!啟動了

大家好&#xff0c;我是洋子。今年的春招很多企業已經開始招聘了&#xff0c;像美團今年繼續發力&#xff0c;24屆春招以及25屆暑期轉正實習一共招聘4000人。另外&#xff0c;阿里&#xff0c;京東&#xff0c;順豐等公司也已經開始春招&#xff0c;可以說招聘的號角已經正式吹…

GO語言學習筆記(與Java的比較學習)(十)

錯誤處理與測試 Go 沒有像 Java 和 .NET 那樣的 try/catch 異常機制&#xff1a;不能執行拋異常操作。但是有一套 defer-panic-and-recover 機制 錯誤處理 Go 有一個預先定義的 error 接口類型 type error interface {Error() string } errors 包中有一個 errorString 結構…