当前位置: 首页 > news >正文

如何用低代码的思路设计文字描边渐变组件

前言

文字特效设计一直是困扰 Web 前端 Css 世界多年的问题, 比如如何用纯 Css 实现文字描边, 渐变, 阴影等, 由于受限于浏览器兼容性的问题, 我们不得不使用其他替代方案来实现.

平时工作中我们使用 PS 等设计工具能很容易的实现文字渐变等特效, 但是随着可视化技术的成熟, 我们需要把传统软件的能力移植到 web 端, 让用户在 Web 端也能有和桌面软件一样的体验效果, 那么我们就需要想一套优雅的方案了, 接下来我会从文本特效的

  • 描边

  • 阴影

  • 渐变

这3个纬度来和大家分享一下用前端实现的解决方案, 并提供一种可复用的文本组件设计方案, 让大家更容易的来是使用文字特效.

你将收获

  • 文字渐变, 阴影, 描边的3种方案实现

  • 组件设计的一些通用方法和原则

  • 如果在低代码平台中优雅的设计功能强大的文字组件

  • 技术脑洞

正文

先来介绍一下文字描边和阴影的设计方案.

文字描边的2种css方案

  1. css3text-stroke

我们可以使用如下样式来实现简单的描边效果:

-webkit-text-stroke: 1px #000000;

在w3c上演示的效果如下:

d652e2808c3d839314de5ee5e099e413.png

但是缺点就是兼容性不是特别好, 如果不考虑太多浏览器的兼容问题, 大家可以直接用这种方案.

  1. 使用text-shadow 模仿描边效果

使用此方案有点就是兼容性好, 不需要加浏览器前缀,  方案如下:

.text-shadow {text-shadow: #000 1px 0 0, #000 0 1px 0, #000 -1px 0 0, #000 0 -1px 0;color: #fff;
}

显示效果:

f2e6f340e651365134b6071cc26696fd.png

刚才介绍的文字描边引用了阴影来实现,  自然我们要想实现文字阴影, 可以直接使用text-shadow, 并且我们可以实现多种阴影的效果, 甚至能用它实现3D文字效果(并不建议这么做, 性能有待考量)

32bae912349d0c9a5a513e3c1515b0d3.png

实现文字渐变的3种方案

文字渐变css3也提供了对应的特性, 但是兼容性并不是很好, 目前还不推荐使用, 有如下2种方案:

// 方案1. 背景裁切+背景渐变实现
{background-image: -webkit-gradient(linear, left center, right center, from(blue), to(red)); /* 背景色渐变 */-webkit-background-clip: text;  /* 设置背景的显示区域 */-webkit-text-fill-color: transparent; /* 避免字体颜色覆盖 */
}// 方案2: mask
{-webkit-mask-image: -webkit-gradient(linear, 0 0, 0 bottom, from(red), to(blue));
}

效果如下:

25c7c76d0bfd2b13256c6c3797245ae3.png

根据笔者的实验, 更推荐用另一种兼容性更好的方案—— svg.

接下来我们看看使用svg实现文字渐变的效果.

a07b07f6b8aea99f6d41b70691a520d1.png

具体实现方案大家需要具备一点的 svg 基础知识,  这里给大家分享一下我的实现代码:

<svg style={{width: '100%',textShadow: `${shadow[1]}px ${shadow[0]}px ${shadowSize}px`,
}}><defs><linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" style={{'stopColor': upColor, 'stopOpacity': 1}} /><stop offset="100%" style={{'stopColor': backColor, 'stopOpacity':1}} /></linearGradient></defs><text x={pos[1]} y={pos[0]} fill="url(#grad)" style={{fontSize, textAnchor: 'start'}}>Dooring文字渐变效果</text>
</svg>

以上代码中upColor(前景色), backColor(背景色), 我们可以动态配置, 同时我们还可以改变渐变的方向, 通过linearGradient 标签的xy属性. 大家感兴趣的可以私下研究一下.

通过这种方案, 我们就能实现展现能力非常强的文字特效了. 接下来我会分享一下如何用组件化或者低代码的思路, 将文字特效封装成一个高可复用的组件.

如果优雅的设计功能强大的文字组件

在介绍组件设计思路之前,有必要介绍一下著名的SOLID原则.

SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转)是由罗伯特·C·马丁提出的面向对象编程和面向对象设计的五个基本原则。利用这些原则,程序员能更容易和高效的开发一个可维护和扩展的系统。 SOLID被典型的应用在测试驱动开发上,并且是敏捷开发以及自适应软件开发的基本原则的重要组成部分。

  • S 单一功能原则: 规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。所有它的服务都应该严密的和该功能保持一致。

  • O 开闭原则: 规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。遵循这种原则的代码在扩展时并不需要改变。

  • L 里氏替换原则: 派生类(子类)对象可以在程序中代替其基类(超类)对象,是对子类型的特别定义.

  • I 接口隔离原则: 指明应用或者对象应该不依赖于它不使用的方法。接口隔离原则(ISP)拆分非常庞大臃肿的接口成为更小的和更具体的接口,这样应用或对象只需要知道它们感兴趣的方法。这种缩小的接口也被称为角色接口。接口隔离原则(ISP)的目的是系统去耦合,从而容易重构,更改和重新部署。接口隔离原则是在SOLID (面向对象设计)中五个面向对象设计(OOD)的原则之一,类似于在GRASP (面向对象设计)中的高内聚性。

  • D 依赖反转原则: 是指一种特定的解耦 形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。

掌握好这5个原则将有利于我们开发出更优秀的组件,请默默记住.接下来我们来看看文字特效组件的设计思路.

30d23b8ac12a63c83dd626eabe5bd3ea.png

以上组件设计是结合 组件化 + 低代码 的开发思路设计的, 组件化帮助我们将业务实现封装地更易用, 低代码的思路让我们将组件和业务结合起来, 通过一种更系统的思维来设计组件.

具体在组件场景的用法如下:

<Text fontSize={14} fontFamily=宋体"pos ={[0, 20]}animation="fade in"
>文字渐变
</Text>

这种方式可以更好的让前端工程师无需关注底层实现直接使用复杂功能, 更近一步地考虑, 如果要让组件通过零代码的方式拖拽配置生成, 我们就需要考虑更多系统性的问题, 比如组件的Schema定义, 系统交互事件如何配置, 如何通过属性配置面板来实现组件样式的搭建.

目前我在Dooring零代码平台中的实现方式是对组件配置项设计一套DSL结构, 通过DSL来动态渲染配置项:

const Chart: ChartSchema = {// 配置项列表editAttrs: [{key: 'layerName',type: 'Text',cate: 'base',},{key: 'y',type: 'Number',cate: 'base',},...DataConfig, // 数据配置项...eventConfig, // 事件配置项],// 组件默认属性config: {width: 200,height: 200,zIndex: 1,layerName: '柱状图',labelColor: 'rgba(188,200,212,1)',// ... 其他配置初始值multiColor: ['rgba(91, 143, 249, 1)', 'rgba(91, 143, 249, 1)', 'rgba(91, 143, 249,,1)', 'rgba(91, 143, 249, 1)'],data: [{name: 'A',value: 25,},{name: 'B',value: 66,}],},
}

我们通过遍历  editAttrs 结构就可以得到一个属性配置面板:

13e54929220c305ba79926e7420bbf26.png

按照这样的思路, 我们实现一个兼容低代码平台的文字特效组件结构可能长这样:

import React, { memo, useState, useRef, useEffect } from 'react'
import { ITextConfig } from './schema';
import { cpClick, isEditorPage } from '@/utils/cpTool';
import ani from '../animate.css';
import classnames from 'classnames';const TextCp = memo((props: ITextConfig) => {const { cpName,text, fontSize,fontFamily,pos = [0, 20],dir,bgColor, padding, radius,animation,animationTurn,delay,interaction = {}, // ...} = props;const { type, content } = interaction;const [visible, setVisible] = useState(false);const [isEditable, setEditable] = useState(false);const textRef = useRef<any>(null);const [data, setData] = useState<string>('');const handleClick = () => {cpClick(type, content, () => {setVisible(true)})}const handleDoubleClick = () => {if(!isEditorPage()) {return}setEditable(true);setTimeout(() => {textRef.current.focus();textRef.current.value = text;}, 30)}const handleSaveText = () => {window.handleTextUpdate(textRef.current.value)setEditable(false)}// 数据源...const direction = dir === 'hor' ? {x1: "0%", y1: "0%", x2: "100%", y2:"0%"} : {x1: "0%", y1: "0%", x2: "0%", y2:"100%"}return (<><div className={classnames('dooring-text', animation !== 'none' && ani[`animate__${animation}`])}style={{ fontSize: _gaw(fontSize), fontFamily,fontWeight: +fontWeight,backgroundColor: bgColor,padding,borderRadius: radius,animationIterationCount: animationTurn,animationDelay: delay + 's',letterSpacing: space + 'px',}} onClick={handleClick} onDoubleClick={handleDoubleClick}><svg style={{width: '100%',textShadow: `${shadow[1]}px ${shadow[0]}px ${shadowSize}px`,}}><defs><linearGradient id="grad" {...direction}><stop offset="0%" style={{'stopColor': upColor, 'stopOpacity': 1}} /><stop offset="100%" style={{'stopColor': backColor, 'stopOpacity':1}} /></linearGradient></defs><text x={pos[1]} y={pos[0]} fill="url(#grad)" style={{fontSize, textAnchor: 'start'}}>{ addSpaceEntity(data || text) }</text></svg>{ isEditable && <input ref={textRef} style={{border: 'none',position: 'absolute',top: 0,left: 0,fontSize,fontFamily,width: '100%',height: '100%',textAlign: 'left',color: 'rgba(60,60,60,1)'}} onBlur={handleSaveText} />}</div></>);
});
export default TextCp;

这样我们既可以单独使用组件, 也可以在Dooring零代码平台中通过拖拽的方式更简单地使用组件了.

最后

我们可以通过上面介绍的方式将任何已有组件包装的更扩展, 组件的开发结构变成了:

  • schema(DSL定义)

  • index(组件实现)

这样设计之后组件会有更好的可移植性和扩展性, 当然未来webcompoent更加成熟稳定了, 我们可以通过更健壮的模式来设计组件. 后续我也会持续分享可视化低代码相关的技术实现, 欢迎大家随时和我交流.

更多推荐

  • (10月最新) 前端图形学实战: 从零开发几何画板(vue3 + vite版)

  • 从零开发一款可视化大屏制作平台

  • 如何设计可视化搭建平台的组件商店?

  • Dooring无代码搭建平台技术演进之路

相关文章:

如何用低代码的思路设计文字描边渐变组件

前言 文字特效设计一直是困扰 Web 前端 Css 世界多年的问题, 比如如何用纯 Css 实现文字描边, 渐变, 阴影等, 由于受限于浏览器兼容性的问题, 我们不得不使用其他替代方案来实现. 平时工作中我们使用 PS 等设计工具能很容易的实现文字渐变等特效, 但是随着可视化技术的成熟, 我…...

Linux 网络通信

(一)套接字Socket概念 Socket 中文意思是“插座”&#xff0c;在 Linux 环境下&#xff0c;用于表示进程 x 间网络通信的特殊文件 类型。本质为内核借助缓冲区形成的伪文件。 既然是文件&#xff0c;那么理所当然的&#xff0c;我们可以使用文件描述符引用套接字。Linux 系统…...

借力互联网,民营医院探索互联网医疗服务的发展方向

民营医院互联网医疗服务是指利用互联网技术和平台&#xff0c;为患者提供更加便捷、高效的医疗服务。在当前数字化时代&#xff0c;互联网医疗服务正逐渐成为医疗行业的新趋势&#xff0c;也为民营医院开拓了更广阔的发展空间。下面将围绕这一主题进行讨论&#xff1a; 首先&a…...

office tool plus工具破解word、visio等软件步骤

第一步&#xff1a;下载工具 破解需要用到office tool plus软件 office tool plus软件下载地址&#xff1a;Office Tool Plus 官方网站 - 一键部署 Office 选择其中一个下载到本地&#xff08;本人选择的是第一个的云图小镇下载方式&#xff09; 第二步&#xff1a;启动工具 …...

python之pyqt专栏5-信号与槽1

在上一篇文章&#xff0c;我们了解到如果想要用代码改变QLabel的文本内容&#xff0c;可以调用QLabel类的text()函数。 但是现在有个这样的需求&#xff0c;界面中有一个Button与一个Label&#xff0c;当点击Button时&#xff0c;将Label的内容改变为“Hello world&#xff01;…...

【JMeter】不同场景下的接口请求

场景1: 上传文件接口即Content-Type=multipart/form-data 步骤: 1. 接口url,method以及path正常填写 2.文件上传content-type是multipart/form-data,所以可以勾选【use multipart/form-data】,如果还有其他请求头信息可以添加一个请求头元件 3.请求参…...

十八数字文化受邀参加版博会“区块链+版权”创新应用试点研讨会

2023年11月23日至25日&#xff0c;以“版权新时代 赋能新发展”为主题的第九届中国国际版权博览会在成都市中国西部国际博览城和天府国际会议中心举办。版博会是我国版权领域唯一的综合性、国际性、国家级版权专业博览会&#xff0c;本届版博会由国家版权局主办&#xff0c;四川…...

Centos 7 离线安装(tar) NodeJS 16 和 Vue

目录 一、下载Nodejs二、安装Nodejs2.1、创建安装目录2.2、上传安装包(无网络) or 直接下载(有网络)2.3、解压缩2.4、配置环境变量2.5、创建软连接2.6、更换镜像源2.7、验证是否安装成功 三、安装Vue四、卸载Nodejs 一、下载Nodejs Nodejs&#xff1a;https://nodejs.org/en/ …...

卸载软件最最最彻底的工具——Uninstall Tool

卸载软件最最最彻底的工具——Uninstall Tool Uninstall Tool 是一款功能强大的专业卸载工具。针对一些普通卸载不彻底的问题&#xff0c;它可以做到最优&#xff0c;比如Matlab等软件的卸载难的问题也可以较好地解决。 它比 Windows 自带的“添加/删除程序”功能快 3 倍&…...

2022年MathorCup大数据竞赛B题北京移动用户体验影响因素研究求解全过程文档及程序

2022年MathorCup高校数学建模挑战赛—大数据竞赛 B题 北京移动用户体验影响因素研究 原题再现&#xff1a; 移动通信技术飞速发展&#xff0c;给人们带来了极大便利&#xff0c;人们也越来越离不开移动通信技术带来的各种便捷。随着网络不断的建设&#xff0c;网络覆盖越来越…...

C#,《小白学程序》第二十课:大数的加法(BigInteger Add)

大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算。 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法。 重复了部分 19 课的代码。 1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary>…...

通用功能——git 攻略

摘要 本文主要介绍git常用命令的使用方法&#xff0c;同时介绍一些常见问题的处理方法&#xff0c;持续更新中… git命令通用选项 大多数git命令都适用的选项列表如下&#xff1a; -v, --verbose show hash and subject, give twice for upstream branch -q, --quie…...

LemMinX-Maven:帮助在eclipse中更方便地编辑maven的pom文件

LemMinX-Maven&#xff1a;https://github.com/eclipse/lemminx-maven LemMinX-Maven可以帮助我们在eclipse中更方便地编辑maven工程的pom.xml文件&#xff0c;例如补全、提示等。不用单独安装&#xff0c;因为在安装maven eclipse插件的时候已经自动安装了&#xff1a; 例…...

CAD与 PDM系统如何协同工作的?

在产品研发中&#xff0c;CAD&#xff08;计算机辅助设计&#xff09;和PDM&#xff08;产品数据管理&#xff09;是两个核心的工具&#xff0c;它们在产品从设计到制造的整个生命周期中发挥着重要的作用。虽然这两个工具在功能上有所不同&#xff0c;但它们在使用上却有着密切…...

vue-历史模式部署

项目部署 本项目采用nginx进行部署&#xff0c;历史模式的部署需要服务端的配合&#xff0c;本次采用nginx进行配合。 1 配置 const basePath process.env.VUE_APP_BASE_PATH; module.exports {publicPath: basePath #静态资源的路径 /ecology/ }2 创建路由 const createR…...

『Linux升级路』基础开发工具——make/Makefile

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、认识make/Makefile &#x1f4d2;1.1make/Makefile的优点 &#x1f4d2;…...

Python开发技能实战-如何在Visio中添加和删除任意连接点?

问题 在学习或者工作中&#xff0c;我们经常会借助Visio这个软件绘制流程图&#xff0c;在Visio中一般连接点是固定的&#xff0c;固定的连接点只能绘制一条连接线&#xff0c;如下图所示&#xff1a; 但有时候我们需要在两个方框之间绘制双向连接线&#xff0c;达到以下的效果…...

中科驭数受邀出席2023 ODCC冬季全会,共谋开放数据中心创新发展

近日&#xff0c;2023年开放数据中心委员会&#xff08;简称“ODCC”&#xff09;冬季全会在宁夏银川成功召开&#xff0c;中科驭数作为ODCC的新成员单位&#xff0c;受邀出席本次重要会议。 ▲ 中科驭数正式加入ODCC开放数据中心委员会 开放数据中心委员会是在中国通信标准化…...

Leetcode—907.子数组的最小值之和【中等】

2023每日刷题&#xff08;四十二&#xff09; Leetcode—907.子数组的最小值之和 算法思想 参考自y神思想 实现代码 class Solution { public:int sumSubarrayMins(vector<int>& arr) {long long ans 0;const int mod 1e97;int n arr.size();stack<int>…...

下载文件并重命名

//下载文件并重命名 // 无需数字化归档模版下载 function nodigitalMeth(){ let filenameunescape("/projectapp/ghsjy/template/noNeedDigital.docx")//原文件为英文名字 downloadFileRename(filename,"无需成果数据汇交模版") } // 需要数字化归档模版下…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...