從零實現 Dooring 低代碼印章組件

今天繼續和大家分享一下比較有意思的可視化印章組件的實現.

你將收穫

正文

低代碼組件的基本設計模式

我們都知道任何低代碼或者零代碼搭建產品都非常注重底層搭建協議 (schema), 這些產品通常會設計一套向上兼容且可擴展的 DSL 結構, 來實現頁面元件的標準化配置, 並支持元件的向上擴展:

在設計 H5-Dooring 可視化搭建平臺前, 我也參考了很多標準化軟件數據協議, 給我啓發最大的就是 ODATA 規範, 具體設計細節可以參考我之前的文章:

之所以要介紹低代碼的 schema 設計, 是因爲低代碼組件的設計與開發需要依賴 schema 的定義, 爲了滿足低代碼組件能被用戶實時編輯, 其基本的組成類似如下:

我們只需要在寫普通組件的基礎上加一個 schema 文件即可, 這裏以 Dooring 組件來舉一個例子:

// 組件代碼tsx
import styles from './index.less';
import React, { memo, useState } from 'react';
import { IHeaderConfig } from './schema';

const Header = memo((props: IHeaderConfig) ={
  const { cpName, bgColor, logo, height } = props;

  return (
    <header className={styles.header} style={{ backgroundColor: bgColor, height: height + 'px' }}>
      <div className={styles.logo}>
        H5-dooring
      </div>
    </header>
  );
});

export default Header;


// 組件樣式
.header {
    box-sizing: content-box;
    padding: 3px 12px;
    background-color: #000;
    .logo {
      max-width: 160px;
      overflow: hidden;
      img {
        height: 100%;
        object-fit: contain;
      }
    }
  }

// 組件schema
const Header = {
      editData: [
        ...baseConfig,
        {
          key: 'bgColor',
          name: 背景色,
          type: 'Color',
        },
        {
          key: 'height',
          name: 高,
          type: 'Number',
        },
        {
          key: 'logo',
          name: 'logo',
          type: 'Upload',
          isCrop: false,
          cropRate: 1000 / 618,
        }
      ],
      config: {
        ...baseDefault,
        bgColor: 'rgba(245,245,245,1)',
        logo: [
          {
            uid: '001',
            name: 'image.png',
            status: 'done',
            url: 'http://cdn.dooring.cn/dr/logo.ff7fc6bb.png',
          },
        ],
        height: 50,
      },
    };
    
export default Header;

在初步瞭解了低代碼組件的設計模式之後, 我們接下來就來實現一下低代碼印章組件的實現.

印章組件的設計原理

我們由上圖可以看出, 一個印章組件包含如下幾個部分:

對於印章的繪製, 我們可以採用 canvas 或者 svg 來實現, 這裏我採用 canvas 來實現, 首先我們需要定義組件可以對外暴露的屬性, 以便在低代碼平臺中可以讓用戶來自定義, 這裏我直接列出基本的配置:

接下來我們就來實現一下吧!

1. 繪製印章邊框

let canvas = dom; 
let context = canvas.getContext('2d') as any;

// 初始化
canvas.width= w0;
canvas.height = w0;

// 繪製印章邊框   
let width=canvas.width/2;
let height=canvas.height/2;
context.lineWidth= lineWidth;
context.strokeStyle= color;
context.beginPath();
context.arc(width, height, width - lineWidth, 0, Math.PI*2);
context.stroke();

由上面代碼可知我們用 canvasarc 方法來創建一個圓形邊框.

2. 繪製五角星

創建一個五角星形狀. 該五角星的中心座標爲 (x0, y0), 中心到頂點的距離爲 radius, rotate=0 時一個頂點在對稱軸上

    function create5star(context: any,sx: number,sy: number,radius: number,color: string,rotato: number){
        context.save();  
        context.fillStyle=color;  
        //移動座標原點
        context.translate(sx,sy);  
        //旋轉 
        context.rotate(Math.PI+rotato); 
        //創建路徑 
        context.beginPath(); 
        let x = Math.sin(0);  
        let y= Math.cos(0);  
        let dig = Math.PI/5 *4;  
        for(let i = 0;i< 5;i++){
          //畫五角星的五條邊 
         let x = Math.sin(i*dig);  
         let y = Math.cos(i*dig);  
         context.lineTo(x*radius,y*radius);  
        }   
        context.closePath();  
        context.stroke();  
        context.fill();  
        context.restore();  
    }

3. 繪製印章名稱

context.font = `${fontSize}px Helvetica`;
//設置文本的垂直對齊方式
context.textBaseline = 'middle';
//設置文本的水平對對齊方式
context.textAlign = 'center'; 
context.lineWidth=1;
context.fillStyle = color;
context.fillText(name,width,height+60);

4. 繪製環形印章單位

// 平移到此位置
context.translate(width,height);
    context.font = `${componySize}px Helvetica`
    let count = company.length;// 字數   
    let angle = 4*Math.PI/(3*(count - 1));// 字間角度   
    let chars = company.split("");   
    let c;
    for (let i = 0; i < count; i++){
        // 需要繪製的字符
        c = chars[i];   
        if(i==0)
            context.rotate(5*Math.PI/6);
        else
          context.rotate(angle);
        context.save(); 
        // 平移到此位置,此時字和x軸垂直 
        context.translate(90, 0);
        // 旋轉90度,讓字平行於x軸
        context.rotate(Math.PI/2);
        // 此點爲字的中心點 
        context.fillText(c, 0, 20);  
        context.restore();             
    }

在基本的印章實現之後, 我們來接收屬性配置:

對於低代碼的 schema 配置, 這裏以 H5-Dooring 的組件爲例, 給大家分享一下:

import {
  IColorConfigType,
  IDataListConfigType,
  INumberConfigType,
  ISelectConfigType,
  TColorDefaultType,
  ISwitchConfigType,
  ITextConfigType,
  TNumberDefaultType,
  TTextDefaultType,
} from '@/core/FormComponents/types';
import { ICommonBaseType, baseConfig, baseDefault } from '../../common';
import intl from '@/utils/intl';

const t = intl();
export type TTextSelectKeyType = 'left' | 'right' | 'center';
export type TTextPosSelectKeyType = 'bottom' | 'top';
export type TTextFormatSelectKeyType = 'CODE128' | 'pharmacode'
export type TListEditData = Array<
  IColorConfigType | 
  IDataListConfigType | 
  INumberConfigType | 
  ISelectConfigType<TTextSelectKeyType> | 
  ISelectConfigType<TTextPosSelectKeyType> |
  ISelectConfigType<TTextFormatSelectKeyType> |
  ISwitchConfigType | 
  ITextConfigType 
>;
export interface IListConfig extends ICommonBaseType {
  width: TNumberDefaultType;
  compony: TTextDefaultType;
  componySize: TNumberDefaultType;
  text: TTextDefaultType;
  fontSize: TNumberDefaultType;
  color: TColorDefaultType;
  lineWidth: TNumberDefaultType;
  opacity: TNumberDefaultType;
}

export interface IListSchema {
  editData: TListEditData;
  config: IListConfig;
}

const List: IListSchema = {
  editData: [
    ...baseConfig,
    {
      key: 'width',
      name: t('dr.attr.sealSize'),
      type: 'Number',
    },
    {
      key: 'compony',
      name: t('dr.attr.componyName'),
      type: 'Text',
    },
    {
      key: 'componySize',
      name: t('dr.attr.componySize'),
      type: 'Number',
    },
    {
      key: 'text',
      name: t('dr.attr.sealUnit'),
      type: 'Text',
    },
    {
      key: 'fontSize',
      name: t('dr.attr.fontSize'),
      type: 'Number',
    },
    {
      key: 'color',
      name: t('dr.attr.color'),
      type: 'Color',
    },
    {
      key: 'lineWidth',
      name: t('dr.attr.lineWidth'),
      type: 'Number',
    },
    {
      key: 'opacity',
      name: t('dr.attr.opacity'),
      type: 'Number',
    },
  ],
  config: {
    ...baseDefault,
    cpName: 'Seal',
    width: 180,
    compony: 'Dooring零代碼搭建平臺',
    componySize: 18,
    text: 'H5-Dooring',
    fontSize: 14,
    color: 'rgba(240,0,0,1)',
    lineWidth: 6,
    opacity: 100
  },
};

export default List;

快速將任意組件集成到低代碼平臺

在上面的分析實現中我們可以發現, 只需要把普通組件按照屬性對外暴露出來, 並按照 Dooringschema 定義模式來描述出來, 普通組件就可以立馬變成低代碼組件, 並自動生成組件配置面板:

具體的 schema 描述我在文檔中做了詳細的介紹, 大家感興趣可以參考一下:

總結

後續我會繼續和大家分享一下 H5-Dooring 低代碼的更多實踐和思考, 如果大家對可視化低代碼感興趣也可以參考我的低代碼可視化專欄, 如果大家對圖形學感興趣, 也可以參考我的專欄 100 + 前端幾何學應用案例.

H5-dooring 低代碼

H5-dooring 低代碼

V6.Dooring 可視化大屏搭建平臺

V6.Dooring 可視化大屏搭建平臺

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/_hUeW-NSNt6GkRQW2TCF0Q