英文:
Issue when drawing image on canvas on iPad
问题
我正在进行一个HTML5项目,它将在iPad上的WKWebView中运行。
我一切都是通过编程来完成的。
我的WKWebView框架占满整个屏幕,视口大小为1180x820,
所以我将我的画布尺寸和高度设置为1180x820。
但当我使用drawImage函数在我的画布上显示一个1920x1080的图像时,
图像不适合屏幕(显然),但显示得非常清晰(不模糊)。
_canvasContext.drawImage(imgMenu, 0, 0, 1920, 1080);
所以我在绘制图像时对图像进行了重新缩放,仍然使用drawImage函数。
_canvasContext.drawImage(imgMenu, 0, 0, 1920/2, 1080/2);
图像适合屏幕,但模糊。
缩小的质量真的很差(它真的可以更好,这个例子不是最糟糕的)。
我已经尝试了以下参数
_canvasContext.imageSmoothingEnabled = true;
_canvasContext.webkitImageSmoothingEnabled = true;
_canvasContext.mozImageSmoothingEnabled = true;
_canvasContext.imageSmoothingQuality = "high";
但没有帮助。
也许我做错了什么,我不明白该怎么做。
我的iPad屏幕分辨率为2360x1640,因此显示一个1920x1080的图片不应该是问题。
如果有人能帮助我,那将拯救我的生命 ![]()
最诚挚的问候,
Alex
英文:
I'm working on an HTML5 project, that will run in a WKWebView on iPad.
I'm doing everything programatically.
My WKWebView frame takes the full screen, viewport is 1180x820,
so I set my canvas size and height to 1180x820 too.
Here is my original picture I'd like to display:

But when I'm displaying an 1920x1080 image on my canvas with the drawImage function,
the image does not fit on the screen (obsviously) but is really well displayed (not blurred).
_canvasContext.drawImage(imgMenu,0,0,1920,1080).
So I rescale the image when drawing it, still with the drawImage function.
_canvasContext.drawImage(imgMenu,0,0,1920/2,1080/2)
The image fits in the screen, but is blurred.
The downscaling is really really bad (it really could be better, this example is not the worst one).
I already tried the parameters
_canvasContext.imageSmoothingEnabled = true;
_canvasContext.webkitImageSmoothingEnabled = true;
_canvasContext.mozImageSmoothingEnabled = true;
_canvasContext.imageSmoothingQuality = "high";
It does not help.
Maybe I do something wrong, I don't understand what to do.
Screen resolution of my ipad is 2360x1640, so displaying a 1920x1080 picture should not be a problem.
If anyone could help me, that would save my life ![]()
Best regards,
Alex
答案1
得分: 0
这是有关画布的那些令人讨厌和令人困惑的事情之一。你需要做的是使用devicePixelRatio调整画布的大小。这将增加画布的实际大小,以匹配设备的像素密度。这可以是2,也可以是1.5等…… 视网膜屏幕通常是2。
绘制图像的聪明方式是支持任何图像大小并将其适应到画布区域(通常是缩小)。对于小图像,此代码将放大并失去分辨率。
在代码片段中的注释中提到的,如果你希望画布始终使用1180x820,请确保更改宽度和高度变量:
const width = 1180;
const height = 820;
对于片段的目的,我使用了窗口大小。如果您希望支持其他设备大小,这可能更适合您。
英文:
This is one of those annoying and confusing things about canvas. What you need to do is size the canvas using devicePixelRatio. This will increase the actual size of the canvas to match the pixel density of the device. This could be 2, or 1.5 etc... a retina screen is often 2.
For drawing your image, the smart way is to support any image size and fit it into the canvas area (usually scaling down). With a tiny image, this code will scale up and lose resolution.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const IMAGE_URL = 'https://unsplash.it/1920/1080';
const canvas = document.createElement('canvas');
const _canvasContext = canvas.getContext('2d');
// you will probably want this, unless you want to support many screen sizes in which case you will actually want the window size:
/*
const width = 1180;
const height = 820;
*/
const width = window.innerWidth
const height = window.innerHeight
const ratio = window.devicePixelRatio;
// size the canvas to use pixel ratio
canvas.width = Math.round(width * ratio);
canvas.height = Math.round(height * ratio);
// downsize the canvas with css - making it
// retina compatible
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
document.body.appendChild(canvas);
_canvasContext.fillStyle = 'gray'
_canvasContext.fillRect(0, 0, canvas.width, canvas.height);
function drawImage(url) {
  const img = new Image()
  img.addEventListener('load', () => {
    // find a good scale value to fit the image
    // on the canvas
    const scale = Math.min(
      canvas.width / img.width,
      canvas.height / img.height
    );
    // calculate image size and padding
    const scaledWidth = img.width * scale;
    const scaledHeight = img.height * scale;
    const padX = scaledWidth < canvas.width ? canvas.width - scaledWidth : 0;
    const padY = scaledHeight < canvas.height ? canvas.height - scaledHeight : 0;
    _canvasContext.drawImage(img, padX / 2, padY / 2, scaledWidth, scaledHeight);
  })
  img.src = url;
}
drawImage(IMAGE_URL);
<!-- language: lang-css -->
body,html {
  margin: 0;
  padding: 0;
}
<!-- end snippet -->
As mentioned in a comment in the code snippet. If your want your canvas to always use 1180x820... be sure to change the width and height variables:
  const width = 1180;
  const height = 820;
For the purposes of the snippet I used the window size. Which may be better for you if you wish to support other device sizes.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。



评论