前端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.mzph.cn/news/718055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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…

关于脉冲负载应用中电阻器,您需要了解的 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才可以显示…

C++自学精简实践教程

一、介绍 1.1 教程特点 一篇文章从入门到就业有图有真相&#xff0c;有测试用例&#xff0c;有作业&#xff1b;提供框架代码&#xff0c;作业只需要代码填空规范开发习惯&#xff0c;培养设计能力 1.2 参考书 唯一参考书《C Primer 第5版》​参考书下载&#xff1a; 蓝奏云…

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;可以说招聘的号角已经正式吹…

十二、类与声明

类与声明 什么是类&#xff1f; 前情总结 前面22讲的课基本上就做了两件事 学习C#的基本元素学习类的成员 析构函数&#xff1a; 当对象不再被引用的时候&#xff0c;就会被垃圾回收器gc&#xff0c;回收。而收回的过程当中&#xff0c;如果需要做什么事情&#xff0c;就放在…

远程调用--Http Interface

远程调用--Http Interface 前言1、导入依赖2、定义接口3 创建代理&测试4、创建成配置变量 前言 这个功能是spring boot6提供的新功能&#xff0c;spring允许我们通过自定义接口的方式&#xff0c;给任意位置发送http请求&#xff0c;实现远程调用&#xff0c;可以用来简化…

关于硅金属电阻器?

EAK金属硅电阻器类似于陶瓷复合电阻器&#xff0c;在脉冲负载方面具有优势&#xff0c;需要高峰值功率或高电压与低电感&#xff08;如预充电电路&#xff09;的组合。硅金属电阻器具有更高的连续额定温度&#xff0c;为 350C&#xff0c;而陶瓷电阻器为 250C。这种扩展的温度范…

板子合集1.0

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 原文链接&#xff1a;https://blog.csdn.net/JK01WYX/ 文章目录 1.快速幂板子2.gcd得最大公约数3.堆优化的dijkstra板子4.线段树1板子 区间加线段…

中缀表达式转换逆波兰式(后缀表达式)

算法思路来自于王道的数据结构 #include <iostream> #include <stack> #include <map>using namespace std; string eq; stack<char> op; string rst ""; map<char, int> dict;// 获取优先级 int getPrio(char op) {if (op )return …

SWC Runnable

runnable概念 runnable是编写应用程序行为逻辑的 SWC 的一部分。Runnable 类似于 C 中的函数,类似RTOS中的task,程序运行的实体,swc的灵魂。在 AUTOSAR 中,我们在配置期间在 SWC 中创建 Runnable,并且 在 SWC 的相应源文件中生成Runnable 或函数骨架。骨架函数的名称与我…

【硬件工程师面经整理15_低通/高通/带通滤波器】

低通/高通/带通滤波器 1.1 低通滤波器1.2 高通滤波器1.3 带通滤波器 1.1 低通滤波器 【定义】电感阻止高频信号通过而允许低频信号通过&#xff0c;电容的特性却相反。信号能够通过电感的滤波器、或者通过电容连接到地的滤波器对于低频信号的衰减要比高频信号小&#xff0c;称…