前端canvas项目实战——在线图文编辑器(三):线条宽度&样式

前言

上一篇博文中,我们初步实现了右侧属性栏,通过属性栏,我们可以便捷得修改画布中对象的颜色相关属性。

这篇博文是《前端canvas项目实战——简历制作网站》付费专栏系列博文的第三篇——右侧属性栏(线条宽度&样式),主要的内容有:

  1. 针对线条对象: 扩充属性列表,使用户可以修改画布中选中的线条的宽度和样式(实线、虚线、点线等)。

如有需要,你可以:

  • 点击这里,阅读序文《前端canvas项目实战——在线图文编辑器:序》
  • 点击这里,返回上一篇《前端canvas项目实战——在线图文编辑器(二):颜色》
  • 点击这里,前往下一篇《前端canvas项目实战——在线图文编辑器(四):线条端点样式》

一、效果展示

  • 动手体验
    CodeSandbox会自动对代码进行编译,并提供地址以供体验代码效果
    由于CSDN的链接跳转有问题,会导致页面无法工作,请复制以下链接在浏览器打开:
    https://4z795q.csb.app/

  • 动态效果演示

  • 本节之后,我们的简历能做成什么样子
    我们可以修改线条的宽度和样式了。

二、实现步骤

本节的实现的功能在我们的简历模板上没有太多的改变(只改变了蓝色分隔线的宽度,1 --> 2),但作为一个通用的编辑器,我们实现的功能还是很有价值的。下面开始实现:

1. 实现线条宽度(strokeWidth)的属性模块

这里我们要继续修改上一篇博文中的属性工厂——object-props.js,向其中添加一个控件StrokeWidthWrapper

  const StrokeWidthWrapper = (props) => {
    const strokeWidthOptions = [1, 2, 3, 4, 5];

	// 下拉菜单选项列表
	const optionViews = strokeWidthOptions.map((option, index) => {
      return (
        <Option className="property-stroke-width"
          key={`stroke-width-${option}`} value={option} title={option}>
          <div className="property-stroke-width-line" style={{ height: `${option}px` }} />
        </Option>
      );
    });

    return (
      <div className="property-row" key={props.key}>
        <span className="property-title">宽度</span>
        <div className="property-container">
          <Select value={strokeWidth} bordered={false} style={{ width: "100%" }}
            onChange={(value) => { handleChange("strokeWidth", value) }>
            {optionViews}
          </Select>
        </div>
      </div>
    );
  };

代码很简洁,分为 3 个部分:

  • 定义可选的线条宽度列表strokeWidthOptions,这里我设置了最小为 1,最大为 5,可以根据自己的需要做出调整。
  • 通过strokeWidthOptions构造出下拉菜单的选项列表optionViews
  • 组装模块

注意:

  1. 构造下拉菜单选项的代码中有一行<div className="property-stroke-width-line" style={{ height: ${option}px }} />,这里的作用是将下拉菜单的每个选项绘制成一条宽度对应的线条,如下图所示:
2. 实现一个新模块后,要记得添加到属性列表中:
	const propertyWrapperMap = {
		...
		line: ["StrokeWrapper", "StrokeWidthWrapper"],
		...
	};

2. 实线线条样式(strokeDashArray)的属性模块

strokeDashArraystrokeWidth类似,但实现更复杂一些

  const strokeDashArrayWrapper = (props) => {
    const strokeDashArrayOptions = [
      { key: "实线", fabricValue: null, cssValue: "solid" },
      { key: "虚线", fabricValue: [5, 5], cssValue: "dashed" },
      { key: "点线", fabricValue: [1, 1], cssValue: "dotted" },
    ];

    /**
     * 根据传入的value,返回对应的index
     */
    const mapValueToIndex = (value) => {
      if (null !== value && Array.isArray(value)) {
        for (let i = 1; i < strokeDashArrayOptions.length; i++) {
          if (strokeDashArrayOptions[i].fabricValue[0] === value[0]) {
            return i;
          }
        }
      }
      return 0;
    };

    const optionViews = strokeDashArrayOptions.map((option, index) => {
      return (
        <Option className="property-stroke-width" key={`stroke-dasharray-${index}`}
          value={index} title={option.key}>
          <div className="property-stroke-dasharray-line"
            style={{ borderTopStyle: option.cssValue }} />
        </Option>
      );
    });

    return (
      <div className="property-row" key={props.key}>
        <span className="property-title">线条</span>
        <div className="property-container">
          <Select value={mapValueToIndex(_recoverValue(strokeDashArray, strokeWidth))}
            bordered={false} style={{ width: "100%" }}
            onChange={(value) =>
              let adjustedValue = _adjustValue(strokeDashArrayOptions[value].fabricValue, strokeWidth);
              handleChange("strokeDashArray", adjustedValue);
            }
          >
            {optionViews}
          </Select>
        </div>
      </div>
    );
  };

可以看到,strokeDashArray的实现复杂很多,这里分别讲解:

  • 方法_adjustValue_recoverValue 这两个方法在这里没有给出代码,在下一小节会讲到。
  • 这个模块的 value 不直接设置,设置的是选项列表中的索引index(0, 1, 2, …),原因:
    • antd<Select.Option>不允许设置value=null,且只接受stringnumber类型。
    • fabric.Line.strokeDashArray的默认值是 null,同时接受数组(例如[2, 2])作为参数。
  • strokeWidth类似,这个模块的下拉菜单选项也由<div>标签来绘制。
    • 我们使用的是它的border-top-style来表示线段样式,但其接受的值为string,比如实线为solid,虚线为dashed
    • 所以这个模块的 value 拆分为fabricValuecssValue两个。

strokeDashArray实现的效果如下:


3. 意料之外的“联动”

本以为实现可以到此为止了,但是在测试中发现了一个问题。当我设置线条的样式为虚线(strokeDashArray=[5, 5] 时,如果将线条宽度strokeWidth1逐渐增大到5,一条细的虚线会变成粗的点线,如下图所示:

--->

但按照常理,虚线加粗之后应该仍是虚线! 说明我们的实现还存在问题,对于上述strokeWidthstrokeDashArray两部分代码,我们作出以下调整:

  • strokeWidth作为strokeDashArray的系数 “联动” 起来,例如strokeWidth=1时虚线的strokeDashArray=[5, 5]strokeWidth=2时,strokeDashArray就变为[5 * 2, 5 * 2] = [10, 10]
  • 则有了以下代码,分别用来根据当前的线条宽度缩放strokeDashArray数组中的每一位:
  const _adjustValue = (value, factor) => {
    if (null === value) {
      return null;
    }
    return value.map((item) => item * factor);
  };

  const _recoverValue = (value, factor) => {
    if (null === value) {
      return null;
    }
    return value.map((item) => Math.round(item / factor));
  };
  • 用户修改了线条宽度,应该同时通过_adjustValue_recoverValue更新strokeDashArray。修改strokeWidthWrapper<Select>标签的onChange方法为:
  onChange={(value) => {
    let adjustedValue = _adjustValue(_recoverValue(strokeDashArray, strokeWidth), value);
    handleChange("strokeDashArray", adjustedValue);
    handleChange("strokeWidth", value);
  }}

经过上述的调整,一条虚线的宽度由1放大到5时,仍是虚线。

--->

三、Show u the code

按照惯例,本节的完整代码我也托管在了CodeSandbox中,点击前往,查看完整代码


后记

本节中,我们为线条对象Line实现了修改宽度和样式的属性模块。

在下一节中,我们会为线条两端加上端点,如箭头、圆点、菱形等。

如有需要,你可以:

  • 点击这里,阅读序文《前端canvas项目实战——在线图文编辑器:序》
  • 点击这里,返回上一篇《前端canvas项目实战——在线图文编辑器(二):颜色》
  • 点击这里,前往下一篇《前端canvas项目实战——在线图文编辑器(四):线条端点样式》
  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于Canvas前端图片编辑器是一种可以在Web浏览器中使用的工具,它利用了HTML5Canvas元素来实现图片的编辑和处理功能。 基于Canvas前端图片编辑器具有以下特点和功能: 1. 绘制和编辑:可以在Canvas上进行绘制和编辑图片的各种元素,如线条、矩形、圆形、本等。用户可以通过控制绘制参数,如颜色、粗细和透明度来实现自定义的编辑效果。 2. 滤镜和特效:该编辑器还提供了各种滤镜和特效功能,如黑白、模糊、锐化、亮度调节等。用户可以通过选择不同的滤镜效果来调整图片的颜色和外观。 3. 裁剪和缩放:用户可以使用该编辑器来裁剪和缩放图片,以适应不同的尺寸和比例的需求。裁剪功能允许用户选择需要保留的区域,并将其剪切为新的图片。 4. 图层管理:该编辑器支持图层概念,用户可以根据需要添加、删除和调整图片的各个图层,从而实现复杂的图像组合和叠加效果。 5. 撤销和重做:编辑器还提供了撤销和重做功能,以方便用户进行实时编辑和调整。用户可以随时回退到之前的编辑状态,并重新进行修改。 基于Canvas前端图片编辑器为用户提供了一个友好的界面和简便的操作方式,使得图片编辑和处理变得更加便捷和高效。无需安装任何额外的软件或插件,用户即可在Web浏览器中随时随地进行图片编辑,满足各种个性化和专业化的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IMplementist

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

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

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

打赏作者

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

抵扣说明:

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

余额充值