前端canvas项目实战——简历制作网站(三)——右侧属性栏(线条宽度样式)
目录
- 前言
- 一、效果展示
- 二、实现步骤
- 1. 实现线条宽度(strokeWidth)的属性模块
- 2. 实线线条样式(strokeDashArray)的属性模块
- 3. 意料之外的“联动”
- 三、Show u the code
- 后记
前言
上一篇博文中,我们初步实现了右侧属性栏,通过属性栏,我们可以便捷得修改画布中对象的颜色相关属性。
这篇博文是《前端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 - 组装模块
注意:
- 构造下拉菜单选项的代码中有一行
<div className="property-stroke-width-line" style={{ height:${option}px}} />,这里的作用是将下拉菜单的每个选项绘制成一条宽度对应的线条,如下图所示:2. 实现一个新模块后,要记得添加到属性列表中: ![]()
const propertyWrapperMap = {...line: ["StrokeWrapper", "StrokeWidthWrapper"],...};
2. 实线线条样式(strokeDashArray)的属性模块
strokeDashArray和strokeWidth类似,但实现更复杂一些
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,且只接受string和number类型。fabric.Line.strokeDashArray的默认值是null,同时接受数组(例如[2, 2])作为参数。
- 和
strokeWidth类似,这个模块的下拉菜单选项也由<div>标签来绘制。- 我们使用的是它的
border-top-style来表示线段样式,但其接受的值为string,比如实线为solid,虚线为dashed。 - 所以这个模块的
value拆分为fabricValue和cssValue两个。
- 我们使用的是它的
strokeDashArray实现的效果如下:
3. 意料之外的“联动”
本以为实现可以到此为止了,但是在测试中发现了一个问题。当我设置线条的样式为虚线(strokeDashArray=[5, 5]) 时,如果将线条宽度strokeWidth从1逐渐增大到5,一条细的虚线会变成粗的点线,如下图所示:
--->
但按照常理,虚线加粗之后应该仍是虚线! 说明我们的实现还存在问题,对于上述strokeWidth和strokeDashArray两部分代码,我们作出以下调整:
- 将
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项目实战——简历制作网站(三)——右侧属性栏(线条宽度样式)
目录 前言一、效果展示二、实现步骤1. 实现线条宽度(strokeWidth)的属性模块2. 实线线条样式(strokeDashArray)的属性模块3. 意料之外的“联动” 三、Show u the code后记 前言 上一篇博文中,我们初步实现了右侧属性栏…...
字节跳动二面经典题目
前言 语论即为「语兴式论语」,以语录体及对话的形式,沉淀球友实际工作学习中存在的疑难杂症解答,希望能够更好的帮助到球友和粉丝。欢迎关注公众号:语数 本期投稿 本期语数精选来源于球友应对字节跳动二面时候的场景问题 数仓工程…...
微搭低代码从入门到精通01应用介绍
目录 1 学习路线图2 应用介绍3 编辑器介绍总结 低代码的概念于2014年由 Forrester 首次正式提出。其将低代码定义为:能够以“最少的手写代码”和设置快速开发应用、配置和部署业务应用程序。 不同应用厂商的解法不一样,Gartner评估了400多款低代码/无代码…...
论文阅读《thanking frequency fordeepfake detection》
项目链接:https://github.com/yyk-wew/F3Net 这篇论文从频域的角度出发,提出了频域感知模型用于deepfake检测的模型 整体架构图: 1.FAD: 频域感知分解,其实就是利用DCT变换,将空间域转换为频域ÿ…...
ArcgisForJs快速入门
文章目录 0.引言1.前端代码编辑工具2.使用ArcgisForJs创建一个简单应用3.切片地图服务图层4.动态地图服务图层5.地图事件 0.引言 ArcGIS API for JavaScript是一款由Esri公司开发的用于创建WebGIS应用的JavaScript库。它允许开发者通过调用ArcGIS Server的REST API,…...
【解决方法】git pull报错ssh: connect to host github.com port 22: Connection timed out
问题 git pull ssh: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository.解决方法 在C:\Users\username.ssh文件夹下新建config文件,填入以下文本(如有则直接在文件最后一行新增)&am…...
30天精通Nodejs--第三十天:项目实战-物联网应用
目录 引言架构设计编码创建项目数据服务模拟设备消息接收并保存设备数据后端接口项目启动及接口测试项目启动测试源码地址结语引言 在之前的一系列文章中,我们已系统性地探讨了诸多Node.js相关的技术要点与理论背景。随着知识体系的铺垫到位,我们现在步入了实战环节。接下来…...
java 社区资源管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web社区资源管系统是一套完善的java web信息管理系统 ,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.…...
网络编程套接字(Socket)
为什么需要网络编程??? -丰富的网络资源 每天你在b站上刷着喜欢的up主的视频,实质是通过网络,获取到网络上的一个视频资源 与本地打开文件类似,只是视频文件这个资源来源是网络 所谓的网络编程,其实就是从网络上获取各种数据资源 什么是网络编程?? 网络编程,指的是网络…...
C语言第十一弹---函数(下)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 函数 1、嵌套调用和链式访问 1.1、嵌套调用 1.2、链式访问 2、函数的声明和定义 2.1、单个文件 2.2、多个文件 2.3、static 和 extern 2.3.1、static…...
Unity读书系列《Unity3D游戏开发》——拓展编辑器(一)
文章目录 前言一、扩展Project视图1、右键扩展菜单(Asset)2、监听事件3、拓展布局 二、扩展Hierarchy视图1、拓展菜单(GameObject)2、拓展布局3、重写菜单 三、扩展Inspector视图1、扩展原生组件2、扩展继承组件 四、扩展Scene视图…...
【Git】项目管理笔记
文章目录 本地电脑初始化docker报错.gitignoregit loggit resetgit statusgit ls-filesgit rm -r -f --cached拉取仓库文件更新本地的项目报错处理! [rejected] master -> master (fetch first)gitgitee.com: Permission denied (publickey).error: remote origin already e…...
中文词性标注工具pkuseg例子(运行结果,不太好)
pkuseg_demo.md pkuseg 预训练模型 预训练模型science 安装 pip3 install pkuseg cd /rot/pkuseg_home/model/wget https://github.com/lancopku/pkuseg-python/releases/download/v0.0.25/science.zip uzip science.zip -d ./science/ ls /rot/pkuseg_home/model/science/…...
获取URL参数:split方法、URLSearchParams方法示例
在JavaScript中,可以使用多种方法来获取URL参数,其中常用的方法有split()和URLSearchParams()。 使用split()方法获取URL参数: split()方法将字符串分割成数组。可以使用split()方法将URL分割成协议、主机、路径和查询字符串等部分。然后可…...
SparkSql---用户自定义函数UDFUDAF
文章目录 1.UDF2.UDAF2.1 UDF函数实现原理2.2需求:计算用户平均年龄2.2.1 使用RDD实现2.2.2 使用UDAF弱类型实现2.2.3 使用UDAF强类型实现 1.UDF 用户可以通过 spark.udf 功能添加自定义函数,实现自定义功能。 如:实现需求在用户name前加上"Name:…...
系统架构15 - 软件工程(3)
软件过程模型 瀑布模型特点缺点 原型化模型特点两个阶段不同类型注意 螺旋模型V 模型特点 增量模型特点 喷泉模型基于构件的开发模型(CBSD)形式化方法模型敏捷模型特点“适应性” (adaptive) 而非“预设性” (predictive)“面向人的” (People-oriented) 而非“面向过程的” (P…...
两个近期的计算机领域国际学术会议(软件工程、计算机安全):欢迎投稿
近期,受邀担任两个国际学术会议的Special session共同主席及程序委员会成员(TPC member),欢迎广大学界同行踊跃投稿,分享最新研究成果。期待这个夏天能够在夏威夷檀香山或者加利福尼亚圣荷西与各位学者深入交流。 SERA…...
(二十一)Flask之上下文管理第二篇(细细扣一遍源码)
每篇前言: 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入…...
Java项目:基于SSM框架实现的企业员工岗前培训管理系统(ssm+B/S架构+源码+数据库+毕业论文)
一、项目简介 本项目是一套ssm821基于ssm框架实现的企业员工岗前培训管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格…...
深入了解Redis:选择适用于你的场景的持久化方案
自然语言处理的发展 文章目录 自然语言处理的发展强烈推荐前言:Redis提供了几种主要的持久化方案:RDB快照持久化:工作原理: AOF日志文件持久化:混合持久化: 总结强烈推荐专栏集锦写在最后 强烈推荐 前些天…...
5分钟掌握Goldberg模拟器:告别Steam限制,畅玩单机游戏
5分钟掌握Goldberg模拟器:告别Steam限制,畅玩单机游戏 【免费下载链接】gbe_fork Fork of https://gitlab.com/Mr_Goldberg/goldberg_emulator 项目地址: https://gitcode.com/gh_mirrors/gbe/gbe_fork 你是否厌倦了Steam平台的网络限制ÿ…...
迪文串口屏C51开发避坑指南:从ModBus ASCII模式到音乐播放实战
迪文串口屏C51开发实战:从ModBus ASCII到音乐播放的深度解析 迪文串口屏在工业控制领域占据重要地位,其C51开发环境为开发者提供了高度灵活的定制能力。本文将聚焦三个典型开发场景:ModBus ASCII模式移植、C51变量定义导致的定时问题以及音乐…...
uniapp 雪花算法封装类
1. uniapp 雪花算法封装类 雪花算法(SnowFlake)生成64位整数ID,具有全局唯一、趋势递增、高性能等特点,适合分布式系统。 1.1. 解决分布式全局唯一ID的方法 1.1.1. UUID UUID做全局ID的弊端:UUID是由数字加字母的形式组成,无法保持递增,它使得聚簇索引(主键值和行数据…...
vLLM-v0.17.1保姆级教程:vLLM + Weights Biases 实验跟踪实践
vLLM-v0.17.1保姆级教程:vLLM Weights & Biases 实验跟踪实践 1. vLLM框架简介 vLLM是一个专注于大语言模型推理和服务的开源库,以其出色的性能和易用性在开发者社区中广受欢迎。这个项目最初由加州大学伯克利分校的天空计算实验室发起࿰…...
推理神器Phi-4-mini-reasoning实测:解方程、逻辑题一键生成答案
推理神器Phi-4-mini-reasoning实测:解方程、逻辑题一键生成答案 1. 模型介绍与核心能力 Phi-4-mini-reasoning是一款专注于逻辑推理和数学计算的轻量级AI模型。与通用聊天模型不同,它被专门设计用于处理需要分步推理的任务,能够将复杂的解题…...
保姆级教程:从GEO下载Hi-C数据到HiC-Pro完整分析(避坑指南+实战脚本)
从零开始掌握Hi-C数据分析:HiC-Pro全流程实战与避坑指南 Hi-C技术已经成为三维基因组研究的重要工具,但对于刚接触生物信息学的研究人员来说,从原始数据到最终分析结果的过程往往充满挑战。本文将带你完整走通Hi-C数据分析全流程,…...
Kandinsky-5.0-I2V-Lite-5s镜像免配置优势:内置VAE/CLIP/Qwen2.5-VL,开箱即用
Kandinsky-5.0-I2V-Lite-5s镜像免配置优势:内置VAE/CLIP/Qwen2.5-VL,开箱即用 1. 产品概述 Kandinsky-5.0-I2V-Lite-5s是一款轻量级图生视频模型,专为快速视频创作设计。只需上传一张首帧图片,再补充一句运动或镜头描述…...
别再死记硬背了!一张图帮你理清FS、FT、DTFT、DFS、DFT的来龙去脉
信号处理核心概念可视化指南:从傅里叶级数到离散傅里叶变换的认知地图 当信号处理初学者第一次面对FS、FT、DTFT、DFS、DFT这一系列缩写时,往往会陷入概念迷宫。这些名词背后隐藏着时域与频域、连续与离散、周期与非周期三组关键维度的复杂组合。本文将用…...
【电气数据】电力网络充电站定价策略数据集
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
别再只会用Burp改后缀了!5种Web文件上传绕过技巧原理深度拆解(.htaccess/MIME/00截断)
Web文件上传绕过技术:从原理到实战的深度解析 在CTF竞赛和实际渗透测试中,文件上传漏洞一直是高频出现的攻击面。许多开发者仅仅依赖简单的后缀名过滤或前端验证,却忽视了底层解析机制的复杂性。本文将深入剖析五种主流绕过技术的核心原理&am…...
