签名垫 - 调整大小不起作用

时间:2018-04-30 19:14:27

标签: signaturepad

我正在使用签名板插件,并且我在调整大小事件时遇到了一些问题: - 多次调整会导致质量下降和签名"移动"在浏览器窗口的每个调整大小结束时,画布中没有签名。 - 在某些情况下,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();
        });

1 个答案:

答案 0 :(得分:0)

我在这里提出了一些解决方案; 这是两个主要的DOM元素:

  • div#id_wrapper
  • canvas#id

考虑到它可以应用于具有不同 devicePixelRatio 的设备,并且可以在屏幕上更改其宽度(例如:纵向与横向)。

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

第二次将信号缩放到另一个宽度


  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并重新调整为常规尺寸(其宽度等于100px,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();
  }

使用的库signature pad by szimek 使用过的React和Bootstrap以及一些自定义样式

结果将是

enter image description here

enter image description here