Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i use fromData after toData, and the draw is not completely the same . #270

Closed
c4cat opened this issue Jul 13, 2017 · 16 comments
Closed

i use fromData after toData, and the draw is not completely the same . #270

c4cat opened this issue Jul 13, 2017 · 16 comments
Labels
Milestone

Comments

@c4cat
Copy link

c4cat commented Jul 13, 2017

I don't know why i get data and set data will make the draw different.(the line will become shorter)

I make a demo here https://jsfiddle.net/h80phxyr/7/

There is the pic compare.
https://i.stack.imgur.com/fLNmM.png
https://i.stack.imgur.com/bleJn.png

I use v2.2.0 and chrome 58

Many thanks!

@szimek szimek added the bug label Jul 13, 2017
@szimek
Copy link
Owner

szimek commented Jul 13, 2017

Most likely it's a bug - probably not all data points are stored (the ones at the end of each stroke) and thus when recreating an image from these points, each line is a bit shorter.

@c4cat
Copy link
Author

c4cat commented Jul 13, 2017

@szimek thanks for reply. I will take some time try to fix the bug. By the way, signature pad is a wonderful JavaScript library.

@c4cat
Copy link
Author

c4cat commented Jul 13, 2017

@szimek
I think i found the question.
we should push the end point to this._data when _strokeEnd.
and we should set option throttle 0 - 6.

SignaturePad.prototype._strokeEnd = function (event) {
  var canDrawCurve = this.points.length > 2;
  var point = this.points[0];

  if (!canDrawCurve && point) {
    this._drawDot(point);
  }

  if (typeof this.onEnd === 'function') {
    this.onEnd(event);
  }
 // ************* new add ************
  this._data[this._data.length - 1].push({
    x: point.x,
    y: point.y,
    time: point.time,
    color: this.penColor
  });
 // ************* new add ************
};

@tempbing
Copy link

I also met for this problem.
I'll try it later...

@szimek szimek added this to the 2.2.1 milestone Jul 16, 2017
@szimek szimek closed this as completed in 45db7a2 Jul 23, 2017
@tempbing
Copy link

tempbing commented Jul 24, 2017

@szimek It seems that , this bug is not fixed .


html dom:
<canvas id="signature_container" width="400" height="500"></canvas>
js:

  var signatureId = '#signature_container'; 
  signaturePad = new SignaturePad($(signatureId)[0], {
                backgroundColor: 'rgb(255,255,255)',  
                //penColor: 'green',
                minWidth: 3, 
                maxWidth: 3, 
            });

I used 2.2.1 a moment ago , I see this bug again .

@szimek
Copy link
Owner

szimek commented Jul 24, 2017

@tempbing I don't - check out the jsfiddle (https://jsfiddle.net/h80phxyr/7/) posted by @c4cat. It works fine now. Are you sure that you're using version 2.2.1?

@tempbing Could you update this jsfiddle and try to replicate your issue there?

@tempbing
Copy link

tempbing commented Jul 24, 2017

@szimek I'm sure , and my step like these ..
1.Draw some curves(like letter ‘J’ ) (js code use signaturePad.fromData() + signaturePad.toData())
2. js code use signaturePad.fromDataURL() + signaturePad.toDataURL())

You can see the bug in any step .

Others:
I also see anther problem . When change the setting , signaturePad.minWidth = 5; signaturePad.maxWidth = 10; signaturePad.penColor = "rgb(66, 133, 244)";
use signaturePad.fromData() + signaturePad.toData() . The problem is distinct .

@tempbing
Copy link

tempbing commented Jul 24, 2017

@szimek A new Demo (https://jsfiddle.net/h80phxyr/10/)
You can click "undo" ,then you will see the problem . ( you can draw some curves (like six letters "jjJJjj") ,then click "undo" button six times )

@szimek
Copy link
Owner

szimek commented Jul 24, 2017

Here's a fixed version: https://jsfiddle.net/szimek/h80phxyr/11/ You need to set canvas size in CSS and adjust its size in JS as well. The canvas size adjustment code is based on the code from the demo (https://github.com/szimek/signature_pad/blob/master/example/js/app.js#L11-L19).

@tempbing
Copy link

tempbing commented Jul 25, 2017

@szimek
Thanks very much for reply.
On this fixed version: (https://jsfiddle.net/szimek/h80phxyr/11/)
I see the problem again .
You can draw some curves (like six letters "jjJJjj") ,then click "undo" button six times .
On this online demo.: (https://jsfiddle.net/szimek/h80phxyr/11/)
I have a try ,maybe i don't understand ...
The picture compare.
http://huobei.oss-cn-shenzhen.aliyuncs.com/02.png
http://huobei.oss-cn-shenzhen.aliyuncs.com/01.png
( Can you see my picture ?
Other pic link:
http://foreign-oss.oss-us-west-1.aliyuncs.com/02.png
http://foreign-oss.oss-us-west-1.aliyuncs.com/01.png
)

@szimek
Copy link
Owner

szimek commented Jul 25, 2017

@tempbing Nah, you're right. It's much less noticeable now, but something is still off. I'll check it out.

@UmeshShelke06
Copy link

@szimek , am displaying image on signature-pad...when i draw only on signature-pad and do undo() operation it perform correctly..but when am displaying image on signature-pad and then perform undo then it clear entire image first and then other data..i want to undo only data on image..not an image
my takephoto function()
public takePicture(sourceType, DestinationType) {
var options = {
quality: 100,

  //sourceType: sourceType,
  // destinationType: DestinationType,
  destinationType: this.camera.DestinationType.DATA_URL,
  saveToPhotoAlbum: true,
  correctOrientation: true,
  //mediaType: 2,
  encodingType: this.camera.EncodingType.JPEG,
 mediaType: this.camera.MediaType.PICTURE,
 // allowEdit : true,
  //height:100,
  //width:200,
 
  targetWidth :1000,
  targetHeight:1000,
  // width: window.screen.width,
  // height: window.screen.height,
 
};


this.camera.getPicture(options).then((imagePath) => {
  if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
    this.filePath.resolveNativePath(imagePath)
      .then(filePath => {            
        this.lastImage = this.createFileName();           
        this.tempPath = "data:image/jpeg;base64," + imagePath;
        this.selectedImagePath = imagePath;
       
       //this.signaturePad.fromDataURL(this.tempPath);
      //this.tempPath = this.signaturePad.toDataURL(this.tempPath);
      });

  } else {
   
    this.lastImage = this.createFileName();
   this.tempPath = "data:image/jpeg;base64," + imagePath;
  
 this.selectedImagePath = imagePath;
 this.signaturePad.fromDataURL(this.tempPath);
  // this.selectedImagePath
    this.tempPath = this.signaturePad.toDataURL(this.tempPath);
    // let canvas = document.querySelector('canvas');

    // this.signaturePad.set('canvasWidth', canvas.this.tempath);
    // this.signaturePad.set('canvasHeight', canvas.this.tempath);
    // let tempPathheight =500; 
    // this.signaturePad.set('temPath', tempPathheight);
    //this.tempPath.Height = CanvasHeight;
  }
}, (err) => {
 // this.presentToast(err);
 console.log(err);
});

}

private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}

and my perform()-undo function
perform()
{
var data = this.signaturePad.toData();
if (data) {

      data.pop(); // remove the last dot or line
     this.signaturePad.fromData(data);
  }
   }

please help me to correct my perform() function

@szimek
Copy link
Owner

szimek commented Mar 8, 2018

@amolumesh12 I'm not sure if there's an easy way to do it at the moment, because SignaturePad#fromData clears the canvas before it redraws everything. If you draw your image after calling this method, it would overwrite the signature.

Currently, you could modify the library to remove this.clear() call from SignaturePad#fromData method. I could change this method to not call SignaturePad#clear, but that would be a breaking change and would require releasing a new major version.

@UmeshShelke06
Copy link

can you please make changes in my code for undo operation because..sorry , but am not getting what you trying to say ??

@RDevR99
Copy link

RDevR99 commented Aug 20, 2020

@szimek , am displaying image on signature-pad...when i draw only on signature-pad and do undo() operation it perform correctly..but when am displaying image on signature-pad and then perform undo then it clear entire image first and then other data..i want to undo only data on image..not an image

There is one working solution for what you are desiring.

  1. Copy the data Object (Obtained from "toData()") to a local variable
  2. Pop from the local object
  3. Use fromData(localVariable)
  4. You need to create another hidden canvas
  5. Draw your background Image on the hidden canvas first
  6. Draw the actual canvas on the hidden canvas,
  7. Replace the actual canvas with the state of the hidden canvas
  8. For future "undos" modify the data object that you are updating and repeat (2-7).

Here is an example with TS:

undo() {
    const data: Array<any> = this.signaturePad.toData();

    if(this.signaturePadData)
    data.forEach(d => {
      if(!this.signaturePadData.includes(d))
      {
        this.signaturePadData.push(d)
      }
    })
    else this.signaturePadData = data
    
    if(this.signaturePadData && this.signaturePadData.length!=0)
    {
      this.signaturePadData.pop();
      data.pop(); // remove the last dot or line
      this.signaturePad.fromData(this.signaturePadData);
      this.copyCanvas.nativeElement.getContext('2d').drawImage(this.backgroundImage, 0, 0 ,612, 412);
      this.copyCanvas.nativeElement.getContext('2d').drawImage(this.signaturePadElement.nativeElement,0,0,612,412);
      this.clearImage();
      this.signaturePad.canvas.getContext('2d').drawImage(this.copyCanvas.nativeElement, 0, 0 ,612, 412);
    }
  }

@RDevR99
Copy link

RDevR99 commented Aug 26, 2020

@amolumesh12 I'm not sure if there's an easy way to do it at the moment, because SignaturePad#fromData clears the canvas before it redraws everything. If you draw your image after calling this method, it would overwrite the signature.

Currently, you could modify the library to remove this.clear() call from SignaturePad#fromData method. I could change this method to not call SignaturePad#clear, but that would be a breaking change and would require releasing a new major version.

How about we add an optional parameter to fromData() like "doNotClear?:Boolean". It wont break the existing code and will be more flexible.

public fromData(pointGroups: PointGroup[], doNotClear?:Boolean): void {
    
    if(!doNotClear) this.clear();

    this._fromData(
      pointGroups,
      ({ color, curve }) => this._drawCurve({ color, curve }),
      ({ color, point }) => this._drawDot({ color, point }),
    );

    this._data = pointGroups;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants