前端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.hqwc.cn/news/508758.html

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

相关文章

FPGA-串口接收图像写入RAM并读出在TFT显示屏上显示

系统框图&#xff1a; 需要用到的模块有&#xff1a; 1&#xff0c;UART_RX(串口接收模块)&#xff1b; 2&#xff0c;串口接受的数据存放到RAM模块&#xff1b; 3&#xff0c;RAM IP核&#xff1b; 4&#xff0c;时钟IP核 &#xff08;TFT显示屏驱动时钟的产生&#xff09…

微信小程序构建npm失败解决方式

安装完所需要的依赖后&#xff0c;在微信开发者工具菜单栏中选择&#xff1a;“工具” -> “构建 npm”&#xff0c;但是失败。 解决方法&#xff1a;修改 project.config.json 开发者工具创建的项目&#xff0c;miniprogramRoot 默认为 miniprogram&#xff0c;package.js…

【学习笔记】Vue3源码解析:第二部分-实现响应式(4)

课程地址&#xff1a;【已完结】全网最详细Vue3源码解析&#xff01;&#xff08;一行行带你手写Vue3源码&#xff09; 第二部分-实现响应式&#xff08;4&#xff09;&#xff1a;&#xff08;对应课程的第15-17节&#xff09; 第15节&#xff1a;《处理数组修改或者新增》 …

信钰证券:四川黄金超50亿元解禁,紫金矿业等解禁股东浮盈超200%

本周A股限售股解禁规划不到400亿元&#xff0c;环比下降。 除掉新上市公司&#xff0c;本周共有43家公司限售股解禁&#xff0c;解禁数量28.91亿股&#xff0c;以最新收盘价计算&#xff08;下同&#xff09;&#xff0c;解禁市值387.66亿元。 其间&#xff0c;解禁市值超越1…

2.2 mul、div、and、or乘除指令及所有寄存器英文名

汇编语言 1. mul乘指令 两个相乘的数&#xff0c;要么都是8位&#xff0c;要么都是16位 两个8位数相乘 一个默认放在al中&#xff0c;另一个放在8位reg或内存字节单元中8位乘法&#xff0c;结果默认放在ax中例如&#xff1a;计算100*10 100和10小于255&#xff0c;可以做8位…

Java配置49-nginx 反向代理 sftp 服务器

1. 背景 后端服务需要通过部署在跳板机上的 nginx 访问一个外网的 SFTP 服务器。 2. 方法 nginx从 1.9.0 开始&#xff0c;新增加了一个stream模块&#xff0c;用来实现四层协议的转发、代理或者负载均衡等。 首先检查 nginx 版本信息及是否安装了 stream 模块。 进入 ngi…

CommandLineRunner的使用

背景 在项目启动时需要做一些数据预加载或者某些操作&#xff0c;需要怎么办呢&#xff0c;方法其实有好几种&#xff0c;这里主要讲一下SpringBoot提供的CommandLineRunner接口的使用。一、案例说明以及实现 1.实现CommandLineRunner接口 定义一个类实现CommandLineRunner接…

Matlab 最小二乘插值(曲线拟合)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 在多项式插值时,当数据点个数较多时,插值会导致多项式曲线阶数过高,带来不稳定因素。因此我们可以通过固定幂基函数的最高次数 m(m < n),来对我们要拟合的曲线进行降阶。之前的函数形式就可以变为: 二、实现…

QPaint练习000(绘制坐标轴+码表盘)

参考 参考 mychart.h #ifndef MYCHART_H #define MYCHART_H#include <QWidget> #include <QPainter> #include <QString>struct DataNode {int value;QString key; };typedef struct {QString label;double width;QColor color; } CvsInfo;// MyChart继承…

EdgeX Foundry - MQTT 设备服务

文章目录 一、MQTT 设备服务1.概述2.服务配置3.协议属性4.多级 Topics4.1.异步数据4.2.命令 二、连接 MQTT 设备1.docker-comepse2.设备配置文件3.安装自定义配置4.启动 EdgeX Foundry5.创建 MQTT 设备模拟器6.访问 UI6.1. consul6.2. EdgeX Console 7.测试7.1.命令7.2.事件7.3…

命令行启动mongodb服务器的问题及解决方案 -- Unrecognized option: storage.journal

目录 mongodb命令行启动问题 -- Unrecognized option: storage.journal问题日志&#xff1a;问题截图&#xff1a;问题来源&#xff1a;错误原因&#xff1a;解决方式&#xff1a; mongodb命令行启动问题 – Unrecognized option: storage.journal 同样是格式出问题的问题分析和…

如何为在线课程定价以获得最大收益(7个步骤)

如果您是独立内容创建者或小创业者&#xff0c;希望用 WordPress LMS 在线学习和教练网站获利&#xff0c;您可能会意识到构建在线课程并非易事。 您可能已经浏览了迷宫般的选择&#xff1a; 弄清楚要教什么主题&#xff1b;收集您需要的所有设备&#xff1b;决定弹出的标题和…