前端canvas项目实战——在线图文编辑器(五):字体、字号、行间距

本文介绍了如何在前端canvas项目中实现文本框(fabric.Textbox)的字体、字号和行间距编辑功能,包括常量提取、下拉菜单的实现和仅更新选中文字样式的处理。通过实际操作展示了代码实现和使用效果。
摘要由CSDN通过智能技术生成

前言

上一篇博文中,我们扩充了线条对象(fabric.Line)的属性列表,使用户可以为画布中选中的线条增加或修改端点样式(多种剪头、圆形、菱形等)。

这篇博文是《前端canvas项目实战——简历制作网站》付费专栏系列博文的第五篇——右侧属性栏(字体、字号、行间距),主要的内容有:

  1. 针对文本框(fabric.Textbox)对象: 扩充属性列表,使用户可以修改画布中选中的文本框的字体、字号和行间距。
  2. 在实现了整体更新文本框属性的基础上,还实现了仅更新用户选中的部分文字的样式。

如有需要,你可以:

  • 点击这里,阅读序文《前端canvas项目实战——在线图文编辑器:序》
  • 点击这里,返回上一篇《前端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项目实战——在线图文编辑器(四):线条端点样式》
  • 点击这里,前往下一篇《前端canvas项目实战——在线图文编辑器(六):加粗、斜体、下划线、删除线(上)》
  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMplementist

你的鼓励,是我继续写文章的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值