前端canvas项目实战——简历制作网站(三)——右侧属性栏(线条宽度样式)

目录

  • 前言
  • 一、效果展示
  • 二、实现步骤
    • 1. 实现线条宽度(strokeWidth)的属性模块
    • 2. 实线线条样式(strokeDashArray)的属性模块
    • 3. 意料之外的“联动”
  • 三、Show u the code
  • 后记

前言

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

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

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

一、效果展示

  • 动手体验
    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实现了修改宽度和样式的属性模块。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/438603.html

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

相关文章

掌握使用 React 和 Ant Design 的个人博客艺术之美

文章目录 前言在React的海洋中起航安装 Create React App安装Ant Design 打造个性化的博客风格通过路由实现多页面美化与样式定制部署与分享总结 前言 在当今数字时代&#xff0c;个人博客成为表达观点、分享经验和展示技能的独特平台。在这个互联网浪潮中&#xff0c;选择使用…

电商API接口接入|电商爬虫实践附代码案例

1.爬虫是什么 首先应该弄明白一件事&#xff0c;就是什么是爬虫&#xff0c;为什么要爬虫&#xff0c;百度了一下&#xff0c;是这样解释的&#xff1a;网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追…

二叉搜索树操作题目:二叉搜索树中的插入操作

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉搜索树中的插入操作 出处&#xff1a;701. 二叉搜索树中的插入操作 难度 3 级 题目描述 要求 给定二叉搜索…

当身体发出这八个信号时注意了!这有可能就是植物神经紊乱!

植物神经系统是人体自主神经系统的一部分&#xff0c;它调节内脏器官的活动并维持人体内环境的平衡。植物神经紊乱是指植物神经系统失去平衡而引起的一系列身体反应。这些反应可能是不规律、异常或者不适当的。 那么&#xff0c;植物神经紊乱有哪些常见的信号呢&#xff1f;下…

老龄化对投资意味着什么?

1月15日&#xff0c;国务院办公厅印发《关于发展银发经济增进老年人福祉的意见》从4个方面提出26项举措&#xff0c;为我国首个以“银发经济”命名的政策文件。 近期&#xff0c;国信证券分析师王开发布题为《银发经济再思考&#xff1a;老龄化对投资的影响》的报告&#xff0…

Java面试题(11)

59.说一说springMVC的运行流程 1. 用户向服务器发送请求&#xff0c;请求被 Spring 前端控制 Servelt DispatcherServlet 捕获&#xff1b; 2. DispatcherServlet 对请求 URL 进行解析&#xff0c;得到请求资源标识符&#xff08;URI&#xff09;。然后根据该 URI&#xff0c;…

敲黑板啦!CSGO游戏搬砖项目操作注意事项

CSGO游戏搬砖项目怎么赚钱的&#xff0c;利润在哪&#xff1f; 1.两个平台之间币种不一样&#xff0c;就存在一个汇率差&#xff0c;两平台装备价格也不一样&#xff0c;汇率差-价格差利润。 CSGO游戏搬砖项目具体有哪些操作步骤&#xff1f; 1、准备一台电脑&#xff0c;配置…

数字图像处理(实践篇)二十八 使用OpenCV Python中的K-means对图像进行颜色量化处理

目录 1 颜色量化 2 实践 在某些时候,不可避免的某些设备只能生成有限数量的颜色。因此需要执行颜色量化。选择使用cv2.kmeans()函数对颜色量化应用k-means聚类。 1 颜色量化 使用K-means聚类在图像中实现颜色量化的步骤如下: ① 导入依赖库

FTP文件传输协议

一、存储类型 存储类型分为三种 直连式存储&#xff1a;Direct-Attached Storage&#xff0c;简称DAS 存储区域网络&#xff1a;Storage Area Network&#xff0c;简称SAN&#xff08;可以使用空间&#xff0c;管理也是你来管理&#xff09; 网络附加存储&#xff1a;Networ…

【leetcode】232. 用栈实现队列

用栈实现队列 题目链接 typedef int valuetype; typedef struct {valuetype* arr;int top;int capacity; } Stack;void Init(Stack* stack);void Push(Stack* stack, valuetype value); void Pop(Stack* stack);valuetype Top(Stack* stack); int Size(Stack* stack); bool…

C/C++ - 函数进阶(C++)

目录 默认参数 函数重载 内联函数 函数模板 递归函数 回调函数 默认参数 定义 默认参数是在函数声明或定义中指定的具有默认值的函数参数。默认参数允许在调用函数时可以省略对应的参数&#xff0c;使用默认值进行替代。 使用 默认参数可以用于全局函数和成员函数。默认参…

Docker安装RcoketMQ

1、Docker安装RcoketMQ-4.9.4 在同级文件夹创建目录config&#xff0c;并在里面创建文件broker.conf&#xff0c;文件内容如下&#xff1a; brokerClusterNameDefaultCluster brokerNamebroker-a brokerId0 deleteWhen04 fileReservedTime48 brokerRoleASYNC_MASTER flushDis…