- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试将 300dpi 图像绘制到 Canvas 对象,但在 Chrome 中它显示的质量很差。当我使用下面的代码时,它没有改善,但那是因为 devicePixelRatio
与 backingStoreRatio
相同(均为 1
)。
然后我尝试强制更改一些比率并发现以下内容:
ratio
更改为 2
并强制运行缩放代码,则它会以更好的分辨率绘制到 Canvas 上。 ratio
更改为大于 2
的值(例如 3
、4
、5
、6
等)然后它的分辨率差!这一切都是在台式电脑上完成的。
如何确保 Canvas 以高分辨率绘制?
(代码来自:http://www.html5rocks.com/en/tutorials/canvas/hidpi/)
/**
* Writes an image into a canvas taking into
* account the backing store pixel ratio and
* the device pixel ratio.
*
* @author Paul Lewis
* @param {Object} opts The params for drawing an image to the canvas
*/
function drawImage(opts) {
if(!opts.canvas) {
throw("A canvas is required");
}
if(!opts.image) {
throw("Image is required");
}
// get the canvas and context
var canvas = opts.canvas,
context = canvas.getContext('2d'),
image = opts.image,
// now default all the dimension info
srcx = opts.srcx || 0,
srcy = opts.srcy || 0,
srcw = opts.srcw || image.naturalWidth,
srch = opts.srch || image.naturalHeight,
desx = opts.desx || srcx,
desy = opts.desy || srcy,
desw = opts.desw || srcw,
desh = opts.desh || srch,
auto = opts.auto,
// finally query the various pixel ratios
devicePixelRatio = window.devicePixelRatio || 1,
backingStoreRatio = context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1,
ratio = devicePixelRatio / backingStoreRatio;
// ensure we have a value set for auto.
// If auto is set to false then we
// will simply not upscale the canvas
// and the default behaviour will be maintained
if (typeof auto === 'undefined') {
auto = true;
}
// upscale the canvas if the two ratios don't match
if (auto && devicePixelRatio !== backingStoreRatio) {
var oldWidth = canvas.width;
var oldHeight = canvas.height;
canvas.width = oldWidth * ratio;
canvas.height = oldHeight * ratio;
canvas.style.width = oldWidth + 'px';
canvas.style.height = oldHeight + 'px';
// now scale the context to counter
// the fact that we've manually scaled
// our canvas element
context.scale(ratio, ratio);
}
context.drawImage(pic, srcx, srcy, srcw, srch, desx, desy, desw, desh);
}
仅进行以下更改会产生高分辨率 Canvas 图像(为什么?):
//WE FORCE RATIO TO BE 2
ratio = 2;
//WE FORCE IT TO UPSCALE (event though they're equal)
if (auto && devicePixelRatio === backingStoreRatio) {
如果我们把上面的比例改成3
,就不是高分辨率了!
编辑:一个额外的观察——即使是 2x 比率,虽然它的分辨率明显更好,但它仍然不如在 img
标签中显示图像那么清晰)
最佳答案
从问题链接的 HTML5Rocks 文章使事情变得比他们需要的更困难,但它犯了与我看到的其他资源相同的基本错误(1、2、3、4) .这些引用文献对该公式进行了一些修改:
var rect = canvas.getBoundingClientRect();
canvas.width = Math.round (devicePixelRatio * rect.width); // WRONG!
公式错了。更好的公式是
var rect = canvas.getBoundingClientRect();
canvas.width = Math.round (devicePixelRatio * rect.right)
- Math.round (devicePixelRatio * rect.left);
重点是,通过 devicePixelRatio 缩放宽度或高度(即,两个位置的差异)没有意义。您应该只缩放绝对位置。我找不到这个确切点的引用,但我认为这是显而易见的,一旦你明白了。
无法根据矩形的 CSS 宽度和高度(以设备无关像素为单位)计算矩形的物理宽度和高度(以设备像素为单位)。
假设您有两个元素,它们的边界矩形在与设备无关的像素中是
{ left: 0, top: 10, right: 8, bottom: 20, width: 8, height: 10 },
{ left: 1, top: 20, right: 9, bottom: 30, width: 8, height: 10 }.
现在假设 devicePixelRatio 为 1.4,元素将覆盖这些设备像素矩形:
{ left: 0, top: 14, right: 11, bottom: 28, width: 11, height: 14 },
{ left: 1, top: 28, right: 13, bottom: 42, width: 12, height: 14 },
其中 left、top、right 和 bottom 已乘以 devicePixelRatio 并四舍五入到最接近的整数(使用 Math.round())。
您会注意到这两个矩形在与设备无关的像素中具有相同的宽度,但在设备像素中具有不同的宽度。 ▯
这是一个用于测试的代码示例。在浏览器中加载它,然后用鼠标放大和缩小。最后一张 Canvas 应该总是有清晰的线条。其他三个在某些分辨率下会很模糊。
在桌面 Firefox、IE、Edge、Chrome 和 Android Chrome 和 Firefox 上测试。 (注意,这对 JSfiddle 不起作用,因为 getBoundingClientRect 在那里返回不正确的值。)
<!DOCTYPE html>
<html>
<head>
<script>
function resize() {
var canvases = document.getElementsByTagName("canvas");
var i, j;
for (i = 0; i != canvases.length; ++ i) {
var canvas = canvases[i];
var method = canvas.getAttribute("method");
var dipRect = canvas.getBoundingClientRect();
var context = canvas.getContext("2d");
switch (method) {
case "0":
// Incorrect:
canvas.width = devicePixelRatio * dipRect.width;
canvas.height = devicePixelRatio * dipRect.height;
break;
case "1":
// Incorrect:
canvas.width = Math.round(devicePixelRatio * dipRect.width);
canvas.height = Math.round(devicePixelRatio * dipRect.height);
break;
case "2":
// Incorrect:
canvas.width = Math.floor(devicePixelRatio * dipRect.width);
canvas.height = Math.floor(devicePixelRatio * dipRect.height);
break;
case "3":
// Correct:
canvas.width = Math.round(devicePixelRatio * dipRect.right)
- Math.round(devicePixelRatio * dipRect.left);
canvas.height = Math.round(devicePixelRatio * dipRect.bottom)
- Math.round(devicePixelRatio * dipRect.top);
break;
}
console.log("method " + method
+ ", devicePixelRatio " + devicePixelRatio
+ ", client rect (DI px) (" + dipRect.left + ", " + dipRect.top + ")"
+ ", " + dipRect.width + " x " + dipRect.height
+ ", canvas width, height (logical px) " + canvas.width + ", " + canvas.height);
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "cyan";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "black";
for (j = 0; j != Math.floor (canvas.width / 2); ++ j) {
context.fillRect(2 * j, 0, 1, canvas.height);
}
}
};
addEventListener("DOMContentLoaded", resize);
addEventListener("resize", resize);
</script>
</head>
<body>
<canvas method="0" style="position: absolute; left: 1px; top: 10px; width: 8px; height: 10px"></canvas>
<canvas method="1" style="position: absolute; left: 1px; top: 25px; width: 8px; height: 10px"></canvas>
<canvas method="2" style="position: absolute; left: 1px; top: 40px; width: 8px; height: 10px"></canvas>
<canvas method="3" style="position: absolute; left: 1px; top: 55px; width: 8px; height: 10px"></canvas>
</body>
</html>
关于javascript - 如何在 Chrome 上以高分辨率绘制 Canvas ?为什么如果 devicePixelRatio === webkitBackingStorePixelRatio 缩放到 2 倍会提高分辨率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19142993/
我正在寻找一种方法来创建根据价格选择我的产品的过滤器(选择下拉菜单)。 我知道这样的查询是完全可能的: SELECT * FROM products ORDER BY price ASC SELECT
函数参数中或显示尺寸时(高度,宽度)的顺序是否有约定? 最佳答案 我不知道大量的语言,但我使用过的语言(宽度,高度)。它更适合沿着 (x, y) 坐标线。 关于language-agnostic -
在我的表单中,我让用户输入房间的长度高度和宽度以获得 m2、m3 和瓦特的计算值。但是用户也应该能够直接输入 height 和 m2 来获取值。我尝试了很多语法,但 if else 不能正常工作。我知
我在 Elasticsearch 中创建了一个索引,看起来像 {"amazingdocs":{"aliases":{},"mappings":{"properties":{"Adj Close":{"
我有以下功能,我需要清除数据库中的所有图片列并移动到文件系统。当我一次性完成这一切时,内存太多并且会崩溃。我切换到递归函数并执行 20 次写入和批量操作。 我需要为大约 6 个表执行此操作。我的 Re
我正在编写一个函数来计算 PI 的值,并将其作为 double 值返回。到目前为止,一切都很好。但是一旦函数到达小数点后14位,它就不能再保存了。我假设这是因为 double 有限。我应该怎么做才能继
2020年是中国CDN行业从98年诞生到今天快速发展的第二十四年,相关数据显示,全国感知网速持续上扬,达到了3.29兆/秒,标志着在宽带中国的政策指导下,中国的网速水平正在大步赶上世界发达国家的水平
在 aerospike 集合中,我们有四个 bin userId、adId、timestamp、eventype,主键是 userId:timestamp。在 userId 上创建二级索引以获取特定用
$('#container').highcharts('Map', { title : { text : 'Highmaps basic demo'
有没有办法显示自定义宽度/高度的YouTube视频? 最佳答案 在YouTube网站上的this link中: You can resize the player by editing the obj
我使用 Highcharts ,我想在 Highcharts 状态下悬停时制作动态不同的颜色。 正如你可以看到不同的颜色,这就是我做的 var usMapChart , data = [] ; va
在所有节点上运行 tpstats 后。我看到很多节点都有大量的 ALL TIME BLOCKED NTR。我们有一个 4 节点集群,NTR ALL TIME BLOCKED 的值为: 节点 1:239
我发现 APC 上存在大量碎片 (>80%),但实际上性能似乎相当不错。我有 read another post这建议在 wordpress/w3tc 中禁用对象缓存,但我想知道减少碎片是否比首先缓存
对于我的脚本类(class),我们必须制作更高/更低的游戏。到目前为止,这是我的代码: import random seedVal = int(input("What seed should be u
我发现 APC 上存在大量碎片 (>80%),但实际上性能似乎相当不错。我有 read another post这建议在 wordpress/w3tc 中禁用对象缓存,但我想知道减少碎片是否比首先缓存
对于我的脚本类(class),我们必须制作更高/更低的游戏。到目前为止,这是我的代码: import random seedVal = int(input("What seed should be u
我已经 seen >2 字节的 unicode 代码点,如 U+10000 可以成对编写,如 \uD800\uDC00。它们似乎以半字节 d 开头,但我只注意到了这一点。 这个 split Actio
有人可以帮我理解为什么我的饼图百分比计算不正确吗?看截图: 根据我的计算,如 RHS 上所示,支出百分比应为 24.73%。传递给 Highcharts 的值如下:- 花费:204827099.36-
我阅读了有关该问题的所有答案,但我还没有找到任何解决方案。 我有一个应用程序,由我的 api 服务器提供。 Wildfly 8.1 和 Mysql 5.6。当查看时间到来时(Wildfly 服务器连接
我正在用选定的项目创建圆形导航。当用户单击任何项目时,它将移动到定义的特定点。一切都很好,除了当你继续点击项目时,当动画表现不同并且项目在 360 度圆中移动并且它被重置直到你重复场景时,我希望它
我是一名优秀的程序员,十分优秀!