美文网首页
React 横屏签名

React 横屏签名

作者: 清霆 | 来源:发表于2024-07-09 10:49 被阅读0次
    import clsx from 'clsx';
    import { useEffect, useRef, useState } from 'react';
    import type { CSSProperties } from 'react';
    import { Popup } from 'react-vant'; // 不推荐使用移动端特色组件库
    import SignatureCanvas from 'react-signature-canvas';
    
    interface Props {
      open: boolean;
      onOpenChange: (value?: boolean) => void;
      onChange: (value?: string) => void;
    }
    export default function Sign({ open, onOpenChange, onChange }: Props) {
      const signCanvas = useRef<SignatureCanvas>(null);
      const [signVisible, setSignVisible] = useState(false);
    
      useEffect(() => {
        setSignVisible(open);
      }, [open]);
    
      const confirm = () => {
        const sign = signCanvas.current!.toDataURL('image/png')!;
        onChange(sign);
        onOpenChange(false);
      };
    
      return (
        <Popup
          className={'sign-contracted-modal'}
          visible={signVisible}
          onClose={() => setSignVisible(false)}
          position="top"
          onOpen={() => {
            detectOrient(signCanvas.current!);
          }}
        >
          <div className={'sign-contracted'} id="sign-contracted">
            <div id="sign-content" className={'sign-content'}>
              <SignatureCanvas
                ref={signCanvas}
                penColor="black"
                backgroundColor="#F5F5F5"
                canvasProps={{
                  width: 200,
                  height: 200,
                  className: 'signCanvas',
                }}
              />
              <div className={'sign-bar'}>
                <div className={'actions'}>
                  <div
                    className={'btn'}
                    onClick={() => {
                      signCanvas.current?.clear();
                    }}
                  >
                    清除
                  </div>
                  <div
                    className={clsx(['btn', 'submit'])}
                    onClick={() => confirm()}
                  >
                    确认
                  </div>
                </div>
              </div>
            </div>
          </div>
        </Popup>
      );
    }
    
    function detectOrient(
      signCanvas?: SignatureCanvas,
      backgroundColor = 'transparent',
    ) {
      if (!signCanvas) {
        return;
      }
      const width = document.documentElement.clientWidth;
      const height = document.documentElement.clientHeight;
      if (width >= height) {
        return;
      }
      //将整个h5页面翻转
      const $wrapper = document.getElementById('sign-contracted')!;
      if (!$wrapper) {
        return;
      }
      const style: CSSProperties = {
        width: `${height}px`,
        height: `${width}px`,
        transform: `rotate(90deg)`,
        transformOrigin: `${width / 2}px ${width / 2}px`,
        // '-webkit-transform':`rotate(90deg)`,
        // '-webkit-transform-origin':`${width / 2}px ${width / 2}px`,
      };
    
      $wrapper.style.cssText = js2Css(style);
      //将签名还原翻转,就可以保证在横屏情况下保证画笔的方向跟手势一致,然后再进行高度和宽度的调整。
      const parentElement = document.getElementById('sign-content')!;
      const pw = parentElement.clientWidth;
      const ph = parentElement.clientHeight;
      parentElement.style.cssText = `height: ${ph}px;`;
      const canvasElement = signCanvas.getCanvas();
      canvasElement.height = pw;
      canvasElement.width = ph;
    
      const canvasStyle: CSSProperties = {
        backgroundColor,
        transform: `rotate(-90deg)`,
        transformOrigin: `${ph / 2}px ${ph / 2}px`,
        // '-webkit-transform':`rotate(-90deg)`,
        // '-webkit-transform-origin':`${ph / 2}px ${ph / 2}px`,
      };
      canvasElement.style.cssText = js2Css(canvasStyle);
    }
    
    function js2Css(styleObj: CSSProperties) {
      if (typeof styleObj === 'string') {
        return styleObj;
      }
      return Object.entries(styleObj)
        .filter((item) => item[1] !== undefined && item[1] !== null)
        .map(([property, value]) => `${property}:${value};`)
        .join(' ');
    }
    
    .sign-contracted-modal {
      width: 100%;
      height: 100%;
      .sign-contracted {
        width: 100%;
        height: 100%;
        .sign-content {
          width: 100%;
          height: 100%;
          position: relative;
          .sign-bar {
            width: 100%;
            height: fit-content;
            padding: 0 32px 12px 32px;
            position: absolute;
            left: 0;
            bottom: 0;
            z-index: 10;
            display: flex;
            justify-content: space-between;
            align-items: center;
            .actions {
              display: flex;
              align-items: center;
              gap: 12px;
            }
            .btn {
              width: 108px;
              height: 36px;
              border-radius: 6px;
    
              font-weight: 500;
              font-size: 16px;
              color: #1c64d7;
              border: 1px solid #1c64d7;
              background: #fff;
    
              display: flex;
              justify-content: center;
              align-items: center;
              &.submit {
                background: #1c64d7;
                color: rgba(255, 255, 255, 0.95);
              }
            }
          }
        }
      }
    }
    
    

    相关文章

      网友评论

          本文标题:React 横屏签名

          本文链接:https://www.haomeiwen.com/subject/qtaacjtx.html