almothafar / angular-signature-pad

Angular Component for szimek / signature_pad

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Default settings/setup produce images that are cropped on high DPI devices

thunder033 opened this issue · comments

The default settings and instructions for usage produce SVG images that are cropped when used on a high DPI screen (devicePixelRatio > 1). I'm not sure I'm expecting this to be fixed, but in case someone else encounters this. I think the docs should mention additional configuration is need to handle this scenario.

This is reproducible in Chrome by enabling dev tools and selecting a DPR greater than 1.

Example Data URI
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjUwIDE1MCIgd2lkdGg9IjI1MCIgaGVpZ2h0PSIxNTAiPjxwYXRoIGQ9Ik0gMTI1LjI4NSwyMDUuNDUzIEMgMTI3LjkxNSwyMDMuMTY4IDEyNy43MDcsMjAyLjk5MiAxMzAuMTI5LDIwMC41MzEiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAxMzAuMTI5LDIwMC41MzEgQyAxMzIuMzExLDE5Ny42MTAgMTMyLjQ2NiwxOTcuNzQ4IDEzNC4zODcsMTk0LjYxMyIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDEzNC4zODcsMTk0LjYxMyBDIDEzOS4wMDEsMTg2LjM3OSAxMzkuNzA2LDE4Ni45MzQgMTQ0LjkxOCwxNzkuMTgwIiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMTQ0LjkxOCwxNzkuMTgwIEMgMTU0Ljc5MiwxNjguNDMzIDE1NC4xNjEsMTY3LjkzMyAxNjQuNzA3LDE1Ny43MjMiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAxNjQuNzA3LDE1Ny43MjMgQyAxNzQuMjEyLDE0Ny4xNDIgMTc0LjM2NSwxNDcuMjkwIDE4NC4wNjMsMTM2Ljg5NSIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDE4NC4wNjMsMTM2Ljg5NSBDIDE5NC40OTUsMTI2LjQ0NiAxOTQuMjk0LDEyNi4yNTIgMjA0Ljg3MSwxMTUuOTQxIiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMjA0Ljg3MSwxMTUuOTQxIEMgMjEyLjE3NiwxMDguNDI4IDIxMi4yMzUsMTA4LjQ4NyAyMTkuNTQzLDEwMC45NzciIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAyMTkuNTQzLDEwMC45NzcgQyAyMjQuMDQ2LDkyLjc3NSAyMjMuMzU4LDk3LjExOCAyMjcuMjM0LDkzLjMyMCIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDIyNy4yMzQsOTMuMzIwIEMgMjMxLjQwNiw5Ny44MjYgMjMwLjUyMCw5My44ODIgMjMyLjQ5MiwxMDMuMTkxIiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMjMyLjQ5MiwxMDMuMTkxIEMgMjMzLjk1OCwxMTQuMTkwIDIzNC42MjUsMTEzLjczMiAyMzMuNjcyLDEyNS4xMzMiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAyMzMuNjcyLDEyNS4xMzMgQyAyMzIuOTI1LDEzNC44NTQgMjMzLjQxOSwxMzQuODIyIDIzMS40MTQsMTQ0LjQ1NyIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDIzMS40MTQsMTQ0LjQ1NyBDIDIyOS4yNzIsMTU1LjM1NyAyMjkuNjg5LDE1NS40MjIgMjI3LjE5OSwxNjYuMjcwIiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMjI3LjE5OSwxNjYuMjcwIEMgMjIyLjcwOSwxODAuMDIyIDIyNS44OTksMTczLjExNSAyMjQuNjY4LDE3OS45NzMiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAyMjQuNjY4LDE3OS45NzMgQyAyMzAuMzQ1LDE3Mi45MzEgMjI3LjIxMSwxNzkuOTA5IDIzNi4yMDMsMTY2LjA0MyIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDIzNi4yMDMsMTY2LjA0MyBDIDI0Mi45NDcsMTU2LjMwNSAyNDMuNzQyLDE1Ny4xNzkgMjUxLjQ2MSwxNDguNDY5IiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMjUxLjQ2MSwxNDguNDY5IEMgMjYxLjIxNCwxMzkuNDIzIDI2MC45MTgsMTM5Ljc2NCAyNzIuMTQ1LDEzMi45NjEiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAyNzIuMTQ1LDEzMi45NjEgQyAyNzYuNTMyLDEzMS4xNTQgMjc1LjkxNSwxMzAuNzMyIDI4MC44NjMsMTMxLjA4NiIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDI4MC44NjMsMTMxLjA4NiBDIDI4NC42NTcsMTMwLjY3MyAyODMuNzk0LDEzMS4wNDAgMjg2LjY2OCwxMzIuNzM0IiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMjg2LjY2OCwxMzIuNzM0IEMgMjkyLjM3OCwxMzkuMzk3IDI5Mi40MTksMTM4LjYzMCAyOTYuMzg3LDE0Ny4wMDAiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAyOTYuMzg3LDE0Ny4wMDAgQyAzMDEuNDY0LDE1OS4yMzkgMzAyLjUzOCwxNTguNjY1IDMwNi45ODgsMTcxLjI3MCIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDMwNi45ODgsMTcxLjI3MCBDIDMwOS45OTQsMTgwLjY0NyAzMTAuODU0LDE3OS42ODggMzE1LjE2OCwxODcuODk4IiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMzE1LjE2OCwxODcuODk4IEMgMzE4LjE0OCwxOTEuMzU0IDMxNy4wMDAsMTkwLjQ2NyAzMjEuMDAwLDE5MC45MTAiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAzMjEuMDAwLDE5MC45MTAgQyAzMjYuNTcyLDE4OS4zMTIgMzI1LjQ1MiwxOTAuMjE3IDMyOS43NzcsMTg1LjYyNSIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDMyOS43NzcsMTg1LjYyNSBDIDMzMi4xNTUsMTgwLjc5MCAzMzMuMTQxLDE4MS43NTYgMzM0LjEzNywxNzUuNzk3IiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjxwYXRoIGQ9Ik0gMzM0LjEzNywxNzUuNzk3IEMgMzM2LjkwMSwxNjkuNzY1IDMzNi41NTcsMTY5LjcwMCAzMzguNTgyLDE2My40NDUiIHN0cm9rZS13aWR0aD0iNSIgc3Ryb2tlPSJibGFjayIgZmlsbD0ibm9uZSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTSAzMzguNTgyLDE2My40NDUgQyAzNDAuMDA2LDE1Ny4wOTAgMzQwLjI0NSwxNTcuMTk2IDM0MC44MjQsMTUwLjY2MCIgc3Ryb2tlLXdpZHRoPSI1IiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiPjwvcGF0aD48cGF0aCBkPSJNIDM0MC44MjQsMTUwLjY2MCBDIDM0MC44ODUsMTQ1LjA1NiAzNDEuNTI2LDE0NS4xNDUgMzQxLjYyMSwxMzkuNTU1IiBzdHJva2Utd2lkdGg9IjUiIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+PC9wYXRoPjwvc3ZnPg==

It can be remedied by calling redrawCanvas, but that's not mentioned anywhere, and that method also differs in behavior from how the canvas width and height are handled when set via option (where DPR is basically ignored and the canvas is not rescaled). If you set a width/height via options and then call redrawCanvas(), then your canvas changes size depending on the device.

I had to implement a handler on window resize to get reasonable behavior from this component:

const canvas = signaturePad.getCanvas();
const offsetWidth = this.element.nativeElement.offsetWidth;
canvas.style.width = `${offsetWidth}px`;
canvas.style.height = `${offsetWidth * (options.canvasHeight / options.canvasWidth)}px`;

// can't call redrawCanvas here because we don't want everything cleared, maybe it should be a method flag
const ratio: number = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext('2d').scale(ratio, ratio);

This may not be the correct code for every situation, but something like this is necessary; it doesn't work out of the box.