React实现H5横屏电子签名板

一、前言:
在我准备下班的实话,突然需求方的一个电话制止了我电脑的关机。原来是需求方发现bug,就是点击签名按钮不起作用。后经查询问题发现,之前这个签字板的功能是一个原生app提供的能力,现在要将H5嵌入其他app中,其他app没有通过签字板的能力,导致按钮作用。故解决问题的策略是制作一个H5的签字板。
二、签字板的板式:
React实现H5横屏电子签名板_第1张图片

三、解决步骤:
1、使用react-signature-canvas插件
下载命令:npm i react-signature-canvas -S 或者 yarn add react-signature-canvas
2、获取设备的宽度和高度,再设置底层 canvas 的宽度和高度
3、利用 css 的 transform:rotate(90deg)transform-origin: 301px 301px;canvas 旋转90度,并定位好位置

四、主要代码(本次将 SignatureProps 制作成一个组件)
1、Signature.tsx 代码:

import React, { FC, useState, useEffect, useRef } from 'react';
import { history } from 'alita';
import SignatureCanvas from 'react-signature-canvas';
import styles from './index.less';

interface SignatureProps {
  getSigin: (imgStr: string) => any;
  getCanvasRef?: (ref: React.MutableRefObject<null>) => void;
  back: () => void;
}
const Signature: FC<SignatureProps> = (props) => {
  const { getSigin, getCanvasRef, back } = props;
  const signCanvas = useRef(null);
  useEffect(() => {
    // 竖屏模式下横过来,横屏状态下不变
    var width = document.documentElement.clientWidth;
    var height = document.documentElement.clientHeight;
    if (width < height) {
      detectOrient();
    }
  }, []);
  const confirmSign = () => {
    const sign = signCanvas!.current.toDataURL('image/png');
    getSigin(sign);
  };

  const detectOrient = function (id = 'content') {
    //先将整个h5页面翻转
    let width = document.documentElement.clientWidth;
    let height = document.documentElement.clientHeight,
      $wrapper = document.getElementById(id),
      style = '',
      canvasStyle = '';
    style += 'width:' + height + 'px;';
    style += 'height:' + width + 'px;';
    style += '-webkit-transform: rotate(90deg); transform: rotate(90deg);';
    style += '-webkit-transform-origin: ' + width / 2 + 'px ' + width / 2 + 'px;';
    style += 'transform-origin: ' + width / 2 + 'px ' + width / 2 + 'px;';
    $wrapper!.style.cssText = style;
    //将签名还原翻转,就可以保证在横屏情况下保证画笔的方向跟手势一致,然后再进行高度和宽度的调整。
    let parentElement = document.getElementById('signContent');
    let pw = parentElement!.clientWidth;
    let ph = parentElement!.clientHeight - 10;
    parentElement!.style.cssText = 'height: ' + ph * 2 + 'px;padding: 0 20px;';

    let canvasElement = signCanvas?.current.getCanvas();
    canvasElement.height = pw - 40;
    canvasElement.width = ph * 2;
    canvasStyle += 'transform-origin: ' + ph + 'px ' + ph + 'px;transform: rotate(-90deg);';
    canvasStyle += 'background: #f2f2f2;' + `height:${pw - 40};width:${ph * 2}`;
    canvasElement.style.cssText = canvasStyle;
  };

  return (
    <div className={styles.sign} id="content">
      <div className={styles.signContainer}>
        <div className={styles.salarySignContainer}>
          <div className={styles.salarySignTitle}>
            <div
              className={styles.goBack}
              onClick={() => {
                back();
              }}
            >
              返回
            </div>
            请签名确认
          </div>
          {/* 画布 */}
          <div id="signContent" className={styles.salarySignContent}>
            <SignatureCanvas
              ref={signCanvas}
              penColor="#000"
              backgroundColor="#f2f2f2"
              canvasProps={{ className: styles.sigCanvas }}
            />
          </div>
          {/* 按钮 */}
          <div className={styles.salarySignBar}>
            <div
              className={styles.salarySignBtn}
              onClick={() => {
                confirmSign();
              }}
            >
              确认
            </div>
            <div
              className={styles.salarySignBtn}
              onClick={() => {
                // history.goBack();
                signCanvas.current?.clear();
              }}
            >
              清除
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};
export default Signature;

2、less 文件代码:

.sign{
  .signContainer{
    .salarySignContainer{
      width: 100%;
      height: 100%;
      .salarySignTitle{
        position: relative;
        padding: 10px;
        color: #fff;
        text-align: center;
        background-color:  #0080CB;
        z-index: 9999;
        .goBack{
          position: absolute;
          padding-left: 20px;
        }
      }
    }
  }
  .salarySignBar{
    display:grid;
    grid-template-columns: 1fr 1fr;
    gap: 60px;
    align-items: center;
    justify-content: space-between;
    padding:10px; 
    z-index: 9999;
    .salarySignBtn{
      padding:10px; 
      color: #fff;
      text-align: center;
      background-color: #FAA71D;
      border-radius: 10px;
    }
  }
}
}

你可能感兴趣的:(react.js,javascript,前端)