当前位置: 首页 > 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,"无需成果数据汇交模版") } // 需要数字化归档模版下…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

路由基础-路由表

本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中&#xff0c;往往存在多个不同的IP网段&#xff0c;数据在不同的IP网段之间交互是需要借助三层设备的&#xff0c;这些设备具备路由能力&#xff0c;能够实现数据的跨网段转发。 路由是数据通信网络中最基…...