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

前言

文字特效设计一直是困扰 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无代码搭建平台技术演进之路

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

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

相关文章

Swagger在php和java项目中的应用

Swagger在php和java项目中的应用 Swagger简介Swagger在java项目中的应用步骤常用注解 Swagger在php项目中的应用 Swagger简介 Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 总体目标是使客户端和文件系统作为服务器以…

MyBatis的功能架构,MyBatis的框架架构设计,Mybatis都有哪些Executor执行器,Mybatis中如何指定使用哪一种Executor执行器

文章目录 MyBatis的功能架构是怎样的把Mybatis的功能架构分为三层&#xff1a; **MyBatis的框架架构设计**是怎么样的架构图如下Mybatis都有哪些Executor执行器&#xff1f;它们之间的区别是什么&#xff1f;Mybatis中如何指定使用哪一种Executor执行器&#xff1f; MyBatis的功…

SASS的导入文件详细教程

文章目录 前言导入SASS文件使用SASS部分文件默认变量值嵌套导入原生的CSS导入后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Sass和Less &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努…

人工智能入门教学——AI代理(AI Agent)

目录 一、简介 二、特征 三、结构 四、工作流程 五、类型 六、应用 一、简介 AI代理 (Artificial Intelligence Agent)是指使用人工智能技术和算法来执行特定任务、解决问题或实现目标的程序或系统。这些代理可以是简单的程序&#xff0c;也可以是复杂的系统&#xff0c…

面向对象编程:Rust的面向对象特性

欢迎关注我的公众号lincyang新自媒体&#xff0c;回复关键字【程序员经典书单】&#xff0c;领取程序员的100本经典书单 大家好&#xff01;我是lincyang。 今天我们将深入探讨Rust语言中的面向对象编程&#xff08;OOP&#xff09;特性&#xff0c;并将其与其他流行编程语言进…

基于U-Net的视网膜血管分割(Pytorch完整版)

基于 U-Net 的视网膜血管分割是一种应用深度学习的方法&#xff0c;特别是 U-Net 结构&#xff0c;用于从眼底图像中分割出视网膜血管。U-Net 是一种全卷积神经网络&#xff08;FCN&#xff09;&#xff0c;通常用于图像分割任务。以下是基于 U-Net 的视网膜血管分割的内容&…

mysql高级知识点

一、mysql架构 连接层&#xff1a;负责接收客户端的连接请求&#xff0c;可以进行授权、认证(验证账号密码)。服务层&#xff1a;负责调用sql接口&#xff0c;对sql语法进行解析&#xff0c;对查询进行优化&#xff0c;缓存。引擎层&#xff1a;是真正进行执行sql的地方&#x…

Linux面试题(二)

目录 17、怎么使一个命令在后台运行? 18、利用 ps 怎么显示所有的进程? 怎么利用 ps 查看指定进程的信息&#xff1f; 19、哪个命令专门用来查看后台任务? 20、把后台任务调到前台执行使用什么命令?把停下的后台任务在后台执行起来用什么命令? 21、终止进程用什么命令…

Vue框架学习笔记——事件修饰符

文章目录 前文提要事件修饰符prevent&#xff08;常用&#xff09;stop&#xff08;不常用&#xff09;事件冒泡stop使用方法三层嵌套下的stop三层嵌套看出的stop&#xff1a; once&#xff08;常用&#xff09;capture&#xff08;不常用&#xff09;self&#xff08;不常用&a…

Vue轻松入门,附带学习笔记和相关案例

目录 一Vue基础 什么是Vue&#xff1f; 补充&#xff1a;mvvm框架 mvvm的组成 详解 Vue的使用方法 1.直接下载并引入 2.通过 CDN 使用 Vue 3.通过npm安装 4.使用Vue CLI创建项目 二插值表达式 什么是插值表达式&#xff1f; 插值表达式的缺点 解决方法 相关代…

【数据结构】树与二叉树(廿五):树搜索指定数据域的结点(算法FindTarget)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点a. 算法FindTargetb. 算法解析c. 代码实现a. 使用指向指针的指针b. 直接返回找到的节点 4. 代码整合 5.3.1 树的存储结构 5.…

VUE限制文件上传大小和上传格式

<el-form-item label"图片&#xff1a;" prop"tempImagePath"><el-uploadclass"upload"accept"image/jpeg":show-file-list"false"list-type"picture-card":headers"{ token: token}":action&…

linux的netstat命令和ss命令

1. 网络状态 State状态LISTENING监听中&#xff0c;服务端需要打开一个socket进行监听&#xff0c;侦听来自远方TCP端口的连接请求ESTABLISHED已连接&#xff0c;代表一个打开的连接&#xff0c;双方可以进行或已经在数据交互了SYN_SENT客户端通过应用程序调用connect发送一个…

人力资源管理后台 === 基础环境+登陆

目录 1.人力资源项目介绍 1.1 项目架构和解决方案 1.2 课程安排 1.3 课程具备能力 1.4 课程地址 2. 拉取项目基础代码 3.项目目录和入口文件介绍 4.App.vue根组件解析 5.基础设置settings.js和导航守卫permission.js 6.Vuex的结构 7.使用模板中的Icon图标 8.扩展…

最新世界银行WDI面板数据(1960-2022年)

The World Development Indicators 是由世界银行编制和发布的全面数据集&#xff0c;旨在提供全球发展的详尽统计信息。这份数据集收录了1960-2022年间&#xff0c;世界266个国家共计1477个指标&#xff0c;涵盖经济、社会、环境、教育、公共卫生等20个领域 一、数据介绍 数据…

chromium通信系统-mojo系统(一)-ipcz系统代码实现-同Node通信

在chromium通信系统-mojo系统(一)-ipcz系统基本概念一文中我们介绍了ipcz的基本概念。 本章我们来通过代码分析它的实现。 handle系统 为了不对上层api暴露太多细节&#xff0c;实现解耦&#xff0c;也方便于传输&#xff0c;ipcz系统使用handle表示一个对象&#xff0c;hand…

MySQL基本SQL语句(下)

MySQL基本SQL语句&#xff08;下&#xff09; 一、扩展常见的数据类型 1、回顾数据表的创建语法 基本语法&#xff1a; mysql> create table 数据表名称(字段名称1 字段类型 字段约束,字段名称2 字段类型 字段约束,...primary key(主键字段 > 不能为空、必须唯一) ) …

WebSocket协议测试实战

当涉及到WebSocket协议测试时&#xff0c;有几个关键方面需要考虑。在本文中&#xff0c;我们将探讨如何使用Python编写WebSocket测试&#xff0c;并使用一些常见的工具和库来简化测试过程。 1、什么是WebSocket协议&#xff1f; WebSocket是一种在客户端和服务器之间提供双向…

KubeVela核心控制器原理浅析

前言 在学习 KubeVela 的核心控制器之前&#xff0c;我们先简单了解一下 KubeVela 的相关知识。 KubeVela 本身是一个应用交付与管理控制平面&#xff0c;它架在 Kubernetes 集群、云平台等基础设施之上&#xff0c;通过开放应用模型来对组件、云服务、运维能力、交付工作流进…

4G模块(EC600N)通过MQTT连接华为云

目录 一、前言 二、EC600N模块使用 1&#xff0e;透传模式 2&#xff0e;非透传模式 3、华为云的MQTT使用教程&#xff1a; 三、具体连接步骤 1、初始化检测 2、打开MQTT客户端网络 3、创建产品 4、创建模型 5、注册设备 6、连接客户端到MQTT服务器 7、发布主题消…