Skip to content

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

@thunder033

Description

@thunder033

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions