html - HTML5 - 在 chrome 和 opera 中的画布上绘制时,缩放的图像模糊
问题描述
当我使用drawImage()函数在画布上绘制缩放图像时,它在 Chrome 和 Opera 中看起来有点模糊,但如果我先绘制全尺寸图像,然后再绘制缩放图像,它看起来很清晰。是什么导致模糊,我该如何解决?
const img = new Image();
const crisptCanvas = document.getElementById('crisp-canvas');
const crispContext = crisptCanvas.getContext('2d');
const blurryCanvas = document.getElementById('blurry-canvas');
const blurryContext = blurryCanvas.getContext('2d');
const sx = 0, sy = 0, sWidth = 1980, sHeight = 1251;
const dx = 0, dy = 0;
const scaleFactor = 0.4762626262626263;
// Draw an image on canvas
function scaleImage(scale, context)
{
const dWidth = (sWidth*scale);
const dHeight = (sHeight*scale);
context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
};
// When image is loaded draw it on both canvases
img.onload = function(){
// First draw the source image in full scale and then using the -scaleFactor
setTimeout(()=> {
scaleImage(1, crispContext);
scaleImage(scaleFactor, crispContext);
}, 0);
// Draw the image using the -scaleFactor
scaleImage(scaleFactor, blurryContext);
}
img.src = "https://i.stack.imgur.com/eWDSw.png"
<canvas width="944" height="596" id="crisp-canvas" ></canvas>
<canvas width="944" height="596" id="blurry-canvas" ></canvas>
解决方案
在一天尝试了我能想到的一切之后,当我在画布上绘制缩放图像时,我无法找到解决方案。
以下是我尝试过的一些事情:
1)我尝试过使用scale()方法,但结果是一样的。
2) 我尝试设置imageSmoothingEnabled属性,它适用于像素化艺术游戏,但对于高分辨率图像,质量很糟糕。
3)我尝试使用window.requestAnimationFrame()方法,而不是在第一个请求中在隐藏的画布上绘制全尺寸图像,然后在我的主画布上绘制缩放图像。效果很好,但是当我更改选项卡(关注另一个选项卡)时,几分钟后,我的主画布上的图像再次变得模糊。然后我添加了一个方法来检查用户何时关注我的标签,使用页面可见性 API,并再次在隐藏的画布上重绘全尺寸图像,但这不起作用。只有隐藏画布上最后绘制的图像是清晰的,而在最后一个之前绘制的所有图像都是模糊的。所以唯一的解决方案是为每个图像创建隐藏的画布,这是不切实际的,所以我不得不尝试另一种方法。
所以这是提出的解决方案:
1)将宽度和高度画布属性设置为我的原始图像大小 1980x1251
2)我使用其样式宽度和高度属性缩放画布
请记住,使用此方法在画布上绘制的所有内容,如形状、文本、线条......也将被缩放。例如,如果您绘制一个矩形 (10x10) 像素。只有当画布宽度和高度样式属性与画布宽度和高度属性匹配时,它的宽度和高度都等于 10px。
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
const img = new Image();
const crispCanvas = document.getElementById('crisp-canvas');
const crispContext = crispCanvas.getContext('2d');
const sx = 0, sy = 0, sWidth = 1980, sHeight = 1251;
const dx = 0, dy = 0;
const scaleFactor = 0.4762626262626263;
// Set crisp canvas width & height properties to match the source image
crispCanvas.width = sWidth;
crispCanvas.height = sHeight;
// Scale the source canvas using width & height style properties
function scaleCanvas(scale, canvas) {
const dWidth = (sWidth*scale);
const dHeight = (sHeight*scale);
canvas.style.width = dWidth + 'px';
canvas.style.height = dHeight + 'px';
}
// When image is loaded, scale the crisp canvas and draw the full size image
img.onload = function(){
scaleCanvas(scaleFactor, crispCanvas);
crispContext.drawImage(img, sx, sy);
}
img.src = "https://i.stack.imgur.com/eWDSw.png";
<canvas id="crisp-canvas" ></canvas>
推荐阅读
- java - Spring WS:在 wsdl 请求中添加自定义 SOAP 标头
- c# - Ghostdoc 不会尝试生成返回信息
- rust - 使用 impl Trait 时如何获得 Deref 强制
- spring - 使用 MockMvc 测试 spring 下载链接时“找不到可接受的表示”
- delphi - 使用 Delphi 应用程序客户端、autentication Base 查询 WSDL-SOAP
- javascript - 更新多个条目的表的特定行
- c# - 如何在 Kofax Capture 中以 PDF 或 JPG 格式导出索引字段的快照?
- fortran - 运行 Fortran 程序时出错(forrtl:严重 (157):程序异常 - 访问冲突)
- python-3.x - 使用python用神经网络计算sin函数
- sql - Oracle sql 如何在以下情况下工作