1

我正在使用签名板插件,但我在调整大小事件时遇到了一些问题: - 多次调整大小会导致质量下降,并且每次调整浏览器窗口大小时签名都会“移动”,并且在画布中没有签名。- 在某些情况下,isEmpty() 函数不起作用,我将能够保存空签名。

可选问题:如何检测 php 端的空签名?

谢谢 :)

在我的代码下面:

$(window).resize(function() {
            resizeCanvas();
        });



        var wrapper1 = document.getElementById("signature-pad"),
            clearButton1 = wrapper1.querySelector("[data-action=clear]"),
            canvas1 = wrapper1.querySelector("canvas"),
            signaturePad1;

        var wrapper2 = document.getElementById("signature-pad-paraphe"),
            clearButton2 = wrapper2.querySelector("[data-action=clear]"),
            canvas2 = wrapper2.querySelector("canvas"),
            signaturePad2;

        // Adjust canvas coordinate space taking into account pixel ratio,
        // to make it look crisp on mobile devices.
        // This also causes canvas to be cleared.

        signaturePad1 = new SignaturePad(canvas1);
        signaturePad2 = new SignaturePad(canvas2);

        function resizeCanvas() {

            //Sauvegarde sig / par
            var sig = signaturePad1.toDataURL(); 
            var par = signaturePad2.toDataURL(); 


            var ratio =  Math.max(window.devicePixelRatio || 1, 1);
            canvas1.width = canvas1.offsetWidth * ratio;
            canvas1.height = canvas1.offsetHeight * ratio;
            canvas1.getContext("2d").scale(ratio, ratio);           
            canvas2.width = canvas2.offsetWidth * ratio;
            canvas2.height = canvas2.offsetHeight * ratio;
            canvas2.getContext("2d").scale(ratio, ratio);

            // redraw
            signaturePad1.fromDataURL(sig); 
            signaturePad2.fromDataURL(par); 

        }

        window.onresize = resizeCanvas;
        resizeCanvas();

        // Init -> retourne la bonne valeur de isEmpty -> !!? Not sure if needed
        signaturePad1.clear();
        signaturePad2.clear();

        var signature = $('#confirm_delete_signature').val();
        if(signature){
            signaturePad1.fromDataURL(signature);
        }

        var paraphe = $('#confirm_delete_paraphe').val();
        if(paraphe){
            signaturePad2.fromDataURL(paraphe);
        }

        clearButton1.addEventListener("click", function (event) {
            signaturePad1.clear();
        });

        clearButton2.addEventListener("click", function (event) {
            signaturePad2.clear();
        });
4

1 回答 1

0

这是我开发的一个小解决方案;这里有两个关键的 DOM 元素:

  • div#id_wrapper
  • 画布#id

考虑到它可以应用于具有不同devicePixelRatio的设备和屏幕上的宽度变化(fi:纵向 - 横向方向)。

export class FlexSignatureComponent extends React.Component {
  state = {
     width: 0,
     lines: [],
     storedValue: undefined,
     validationClass: '', // toggles between 'is-invalid'/'is-valid'
     validationMessage: ''
  }

lib 启动是在组件加载后立即启动的:

  componentDidMount = () => {  
    this.signPad = new SignaturePad(document.getElementById(this.props.htmlid), {
      onEnd: this.onChangeSignaturePad,
      backgroundColor: '#fff'
    });

    if (this.valueHolder.current.value) {
      const data = JSON.parse(this.valueHolder.current.value);

      this.state.lines = data.value;
      this.state.width = 100;
    }

    //you need the next workarounds if you have other onWidnowResize handlers manarging screen width
    //setTimeout-0 workaround to move windowResizeHandling at the end of v8-enging procedures queue
    // otherwise omit setTimeout and envoke func as it is
    setTimeout(this.handleWindowResize, 0);
    window.addEventListener("resize", () => setTimeout(this.handleWindowResize, 0));
  }

首先处理窗口大小变化


  handleWindowResize = () => {
    if (this.state.storedValue) {

      const prevWrapperWidth = this.state.width;
      const currentWrapperWidth = $(`#${this.props.htmlid}_wrapper`).width();
      const scale = prevWrapperWidth / currentWrapperWidth;

      this.state.width = currentWrapperWidth;

      this.setRescaledSignature(this.state.lines, scale);
      this.resetCanvasSize();
      this.signPad.fromData(this.state.lines)

    } else
      this.resetCanvasSize()
  }

第二次 rescaleSignature 到另一个宽度


  setRescaledSignature = (lines, scale) => {
    lines.forEach(line => {
      line.points.forEach(point => {
        point.x /= scale;
        point.y /= scale;
      });
    });
  }

终于更新了画布大小

  resetCanvasSize = () => {
    const canvas = document.getElementById(this.props.htmlid);

    canvas.style.width = '100%';
    canvas.style.height = canvas.offsetWidth / 1.75 + "px";

    canvas.width = canvas.offsetWidth * devicePixelRatio;
    canvas.height = canvas.offsetHeight * devicePixelRatio;

    canvas.getContext("2d").scale(devicePixelRatio, devicePixelRatio);
  }

在这里,我们在每次更改时都将新绘制的线添加到 this.state.lines 并准备要作为 json 提交的线。但在提交之前,他们需要创建 deepCopy 并重新调整为常规尺寸(其宽度等于 100 像素,DPR 为 1)


  onChangeSignaturePad = () => {
    const value = this.signPad.toData();
    this.state.lines = value;

    const currentWrapperWidth = $(`#${this.props.htmlid}_wrapper`).width();

    const scale = currentWrapperWidth / 100;
    const ratio = 1 / devicePixelRatio;

    const linesCopy = JSON.parse(JSON.stringify(value));
    this.setRescaledSignature(linesCopy, scale, ratio);

    const data = {
      signature_configs: {
        devicePixelRatio: 1,
        wrapper_width: 100
      },
      value: linesCopy
    };
    this.state.storedValue = JSON.stringify(data);

    this.validate()
  }

还有一件事是红色按钮滑动以前的签名

  onClickClear = (e) => {
    e.stopPropagation();
    this.signPad.clear();
    this.valueHolder.current.value = null;
    this.validate()
  }

  render() {
    let {label, htmlid} = this.props;
    const {validationClass = ''} = this.state;
    return (
      <div className="form-group fs_form-signature">
        <label>{Label}</label>
        <div className="fs_wr-signature">
          <button className={'fs_btn-clear'} onClick={this.onClickClear}>
            <i className="fas fa-times"></i>
          </button>
          <div id={htmlid + '_wrapper'} className={`w-100 fs_form-control ${validationClass}`}>
            <canvas id={htmlid}/>
          </div>
        </div>
        <div className={' invalid-feedback fs_show-feedback ' + validationClass}>Signature is a mandatory field</div>
      </div>
    )
  }

  postWillUnmount() {
    this.signPad.off();
  }

szimek使用的 lib签名板 使用 React 和 Bootstrap 以及一些自定义样式

结果是

在此处输入图像描述

在此处输入图像描述

于 2020-02-04T12:31:46.537 回答