1j01 / jspaint

🎨 Classic MS Paint, REVIVED + ✨Extras
https://jspaint.app/about
MIT License
7.18k stars 560 forks source link

Dev need help on zoom #237

Closed Amealky closed 3 months ago

Amealky commented 2 years ago

I try to to a paint app for a school project but im stick on the zoom I don't understand in your code how you manage to do a pixel perfect zoom

Can you help me please ? 😄

Thanks in advance !!

1j01 commented 2 years ago

One important thing to note is that on some screens, a CSS pixel is not a device pixel, and so you have to use window.devicePixelRatio if you want a canvas element to line up with device pixels exactly. If you explain further what you're trying to do and where you're struggling I can probably help.

Amealky commented 2 years ago

Hello Thanks for the response ! 😄

I tried to get a pixel grid as you had in your paint.js

like If I use the magnifier I get bigger pixel and my paint draw bigger square ( to represent one pixel on the grid )

I manage to use brensendham algoritm to get the pixel line drawing but not to zoom on it

Its more clear ? Don't hesitate if you need more information and thanks for helping 😄

1j01 commented 2 years ago

Zooming is done by setting the visual dimensions (canvas.style.width/height) differently to the resolution of the canvas (canvas.width/height).

canvas.style.width = canvas.width * magnification;
canvas.style.height = canvas.height * magnification;

By default this will be blurry; to get crisp squares you need to style the canvas also with image-rendering

canvas.style.imageRendering = "pixelated";

But note that on High-DPI screens, there is a pixel scaling applied to make content a reasonable size, and it's not always an integer scale. This scale is available as devicePixelRatio. If the canvas is scaled by a non-integer, when factoring in devicePixelRatio and magnification, then image-rendering of pixelated will give ugly non-square pixels. I don't handle this properly in jspaint yet. You might want something like:

if ((magnification * devicePixelRatio == Math.floor(magnification * devicePixelRatio))) {
    canvas.style.imageRendering = "pixelated";
} else {
    canvas.style.imageRendering = ""; // defaults to smooth
}

See also High DPI Canvas - HTML5 Rocks

Amealky commented 2 years ago

Thanks very much for these informations ! I will try it asap and let you know if it work of course if you want to see the final project let me know I will gladly share it with you

Amealky commented 2 years ago

Thanks its work very well I just forgot to set pixel style as "px" at the end... Also my cursor had now an offset with my line have you an idea ?

1j01 commented 2 years ago

You'll have to divide the mouse coordinates by the magnification, after subtracting the top-left of the canvas.

var rect = canvas.getBoundingClientRect();
var mouseX = (event.clientX - rect.left) / magnification;
var mouseY = (event.clientY - rect.top) / magnification;

maybe divide by devicePixelRatio too (Sorry if this reply is too late, maybe you already figured it out.)

Amealky commented 2 years ago

Oh okay thanks No really no problem its really nice to you to helping me ! since I'm working I not have much time to think about this problem so don't worry

I will try that asap :)

Thanks very much again :)