日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

文字特效設(shè)計(jì)一直是困擾 Web 前端 css 世界多年的問(wèn)題, 比如如何用純 Css 實(shí)現(xiàn)文字描邊, 漸變, 陰影等, 由于受限于瀏覽器兼容性的問(wèn)題, 我們不得不使用其他替代方案來(lái)實(shí)現(xiàn).

平時(shí)工作中我們使用 PS 等設(shè)計(jì)工具能很容易的實(shí)現(xiàn)文字漸變等特效, 但是隨著可視化技術(shù)的成熟, 我們需要把傳統(tǒng)軟件的能力移植到 web 端, 讓用戶在 Web 端也能有和桌面軟件一樣的體驗(yàn)效果, 那么我們就需要想一套優(yōu)雅的方案了, 接下來(lái)我會(huì)從文本特效的

  • 描邊
  • 陰影
  • 漸變

這3個(gè)緯度來(lái)和大家分享一下用前端實(shí)現(xiàn)的解決方案, 并提供一種可復(fù)用的文本組件設(shè)計(jì)方案, 讓大家更容易的來(lái)是使用文字特效.

你將收獲

  • 文字漸變, 陰影, 描邊的3種方案實(shí)現(xiàn)
  • 組件設(shè)計(jì)的一些通用方法和原則
  • 如果在低代碼平臺(tái)中優(yōu)雅的設(shè)計(jì)功能強(qiáng)大的文字組件
  • 技術(shù)腦洞

正文

先來(lái)介紹一下文字描邊和陰影的設(shè)計(jì)方案.

文字描邊的2種css方案

  1. css3 的 text-stroke

我們可以使用如下樣式來(lái)實(shí)現(xiàn)簡(jiǎn)單的描邊效果:

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

在w3c上演示的效果如下:

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件圖片

但是缺點(diǎn)就是兼容性不是特別好, 如果不考慮太多瀏覽器的兼容問(wèn)題, 大家可以直接用這種方案.

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

使用此方案有點(diǎn)就是兼容性好, 不需要加瀏覽器前綴,  方案如下:

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

顯示效果:

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件

剛才介紹的文字描邊引用了陰影來(lái)實(shí)現(xiàn),  自然我們要想實(shí)現(xiàn)文字陰影, 可以直接使用text-shadow, 并且我們可以實(shí)現(xiàn)多種陰影的效果, 甚至能用它實(shí)現(xiàn)3D文字效果(并不建議這么做, 性能有待考量)

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件

實(shí)現(xiàn)文字漸變的3種方案

文字漸變css3也提供了對(duì)應(yīng)的特性, 但是兼容性并不是很好, 目前還不推薦使用, 有如下2種方案:

// 方案1. 背景裁切+背景漸變實(shí)現(xiàn)
{
  background-image: -webkit-gradient(linear, left center, right center, from(blue), to(red)); /* 背景色漸變 */
 -webkit-background-clip: text;  /* 設(shè)置背景的顯示區(qū)域 */
 -webkit-text-fill-color: transparent; /* 避免字體顏色覆蓋 */
}

// 方案2: mask
{
  -webkit-mask-image: -webkit-gradient(linear, 0 0, 0 bottom, from(red), to(blue));
}

效果如下:

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件

根據(jù)筆者的實(shí)驗(yàn), 更推薦用另一種兼容性更好的方案—— svg.

接下來(lái)我們看看使用svg實(shí)現(xiàn)文字漸變的效果.

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件

具體實(shí)現(xiàn)方案大家需要具備一點(diǎn)的 svg 基礎(chǔ)知識(shí),  這里給大家分享一下我的實(shí)現(xiàn)代碼:

<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(背景色), 我們可以動(dòng)態(tài)配置, 同時(shí)我們還可以改變漸變的方向, 通過(guò)linearGradient 標(biāo)簽的xy屬性. 大家感興趣的可以私下研究一下.

通過(guò)這種方案, 我們就能實(shí)現(xiàn)展現(xiàn)能力非常強(qiáng)的文字特效了. 接下來(lái)我會(huì)分享一下如何用組件化或者低代碼的思路, 將文字特效封裝成一個(gè)高可復(fù)用的組件.

如果優(yōu)雅的設(shè)計(jì)功能強(qiáng)大的文字組件

在介紹組件設(shè)計(jì)思路之前,有必要介紹一下著名的SOLID原則.

SOLID(單一功能、開(kāi)閉原則、里氏替換、接口隔離以及依賴反轉(zhuǎn))是由羅伯特·C·馬丁提出的面向?qū)ο缶幊毯兔嫦驅(qū)ο笤O(shè)計(jì)的五個(gè)基本原則。利用這些原則,程序員能更容易和高效的開(kāi)發(fā)一個(gè)可維護(hù)和擴(kuò)展的系統(tǒng)。 SOLID被典型的應(yīng)用在測(cè)試驅(qū)動(dòng)開(kāi)發(fā)上,并且是敏捷開(kāi)發(fā)以及自適應(yīng)軟件開(kāi)發(fā)的基本原則的重要組成部分。

  • S 單一功能原則: 規(guī)定每個(gè)類都應(yīng)該有一個(gè)單一的功能,并且該功能應(yīng)該由這個(gè)類完全封裝起來(lái)。所有它的服務(wù)都應(yīng)該嚴(yán)密的和該功能保持一致。
  • O 開(kāi)閉原則: 規(guī)定“軟件中的對(duì)象(類,模塊,函數(shù)等等)應(yīng)該對(duì)于擴(kuò)展是開(kāi)放的,但是對(duì)于修改是封閉的”,這意味著一個(gè)實(shí)體是允許在不改變它的源代碼的前提下變更它的行為。遵循這種原則的代碼在擴(kuò)展時(shí)并不需要改變。
  • L 里氏替換原則: 派生類(子類)對(duì)象可以在程序中代替其基類(超類)對(duì)象,是對(duì)子類型的特別定義.
  • I 接口隔離原則: 指明應(yīng)用或者對(duì)象應(yīng)該不依賴于它不使用的方法。接口隔離原則(ISP)拆分非常龐大臃腫的接口成為更小的和更具體的接口,這樣應(yīng)用或?qū)ο笾恍枰浪鼈兏信d趣的方法。這種縮小的接口也被稱為角色接口。接口隔離原則(ISP)的目的是系統(tǒng)去耦合,從而容易重構(gòu),更改和重新部署。接口隔離原則是在SOLID (面向?qū)ο笤O(shè)計(jì))中五個(gè)面向?qū)ο笤O(shè)計(jì)(OOD)的原則之一,類似于在GRASP (面向?qū)ο笤O(shè)計(jì))中的高內(nèi)聚性。
  • D 依賴反轉(zhuǎn)原則: 是指一種特定的解耦 形式,使得高層次的模塊不依賴于低層次的模塊的實(shí)現(xiàn)細(xì)節(jié),依賴關(guān)系被顛倒(反轉(zhuǎn)),從而使得低層次模塊依賴于高層次模塊的需求抽象。

掌握好這5個(gè)原則將有利于我們開(kāi)發(fā)出更優(yōu)秀的組件,請(qǐng)默默記住.接下來(lái)我們來(lái)看看文字特效組件的設(shè)計(jì)思路.

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件圖片

以上組件設(shè)計(jì)是結(jié)合 組件化 + 低代碼 的開(kāi)發(fā)思路設(shè)計(jì)的, 組件化幫助我們將業(yè)務(wù)實(shí)現(xiàn)封裝地更易用, 低代碼的思路讓我們將組件和業(yè)務(wù)結(jié)合起來(lái), 通過(guò)一種更系統(tǒng)的思維來(lái)設(shè)計(jì)組件.

具體在組件場(chǎng)景的用法如下:

<Text 
  fontSize={14} 
  fontFamily=宋體"
  pos ={[0, 20]}
  animation="fade in"
>
    文字漸變
</Text>

這種方式可以更好的讓前端工程師無(wú)需關(guān)注底層實(shí)現(xiàn)直接使用復(fù)雜功能, 更近一步地考慮, 如果要讓組件通過(guò)零代碼的方式拖拽配置生成, 我們就需要考慮更多系統(tǒng)性的問(wèn)題, 比如組件的Schema定義, 系統(tǒng)交互事件如何配置, 如何通過(guò)屬性配置面板來(lái)實(shí)現(xiàn)組件樣式的搭建.

目前我在Dooring零代碼平臺(tái)中的實(shí)現(xiàn)方式是對(duì)組件配置項(xiàng)設(shè)計(jì)一套DSL結(jié)構(gòu), 通過(guò)DSL來(lái)動(dòng)態(tài)渲染配置項(xiàng):

const Chart: ChartSchema = {
  // 配置項(xiàng)列表
  editAttrs: [
    {
      key: 'layerName',
      type: 'Text',
      cate: 'base',
    },
    {
      key: 'y',
      type: 'Number',
      cate: 'base',
    },
    ...DataConfig, // 數(shù)據(jù)配置項(xiàng)
    ...eventConfig, // 事件配置項(xiàng)
    
  ],
  // 組件默認(rèn)屬性
  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,
      }
    ],
  },
}

我們通過(guò)遍歷  editAttrs 結(jié)構(gòu)就可以得到一個(gè)屬性配置面板:

如何用低代碼的思路設(shè)計(jì)文字描邊漸變組件圖片

按照這樣的思路, 我們實(shí)現(xiàn)一個(gè)兼容低代碼平臺(tái)的文字特效組件結(jié)構(gòu)可能長(zhǎng)這樣:

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)
  }

  // 數(shù)據(jù)源...

  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;

這樣我們既可以單獨(dú)使用組件, 也可以在Dooring零代碼平臺(tái)中通過(guò)拖拽的方式更簡(jiǎn)單地使用組件了.

最后

我們可以通過(guò)上面介紹的方式將任何已有組件包裝的更擴(kuò)展, 組件的開(kāi)發(fā)結(jié)構(gòu)變成了:

  • schema(DSL定義)
  • index(組件實(shí)現(xiàn))

這樣設(shè)計(jì)之后組件會(huì)有更好的可移植性和擴(kuò)展性, 當(dāng)然未來(lái)webcompoent更加成熟穩(wěn)定了, 我們可以通過(guò)更健壯的模式來(lái)設(shè)計(jì)組件. 后續(xù)我也會(huì)持續(xù)分享可視化低代碼相關(guān)的技術(shù)實(shí)現(xiàn), 歡迎大家隨時(shí)和我交流.

分享到:
標(biāo)簽:代碼
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定