Css <;帆布>;在本机分辨率下,尽管放大,视网膜
所以我有一个元素,我在其中画东西。矢量化的东西,而不是像素推动。我想在最大范围的观看条件下,以最少的资源以最高的质量展示。具体来说,我希望确保画布像素和设备像素之间有1:1的映射,以消除模糊、耗时的像素缩放操作 有 我看过“视网膜”显示(结论:devicePixelRatio是你的朋友),但它们都假设在100%变焦下观看。同样地,我也看到过这方面的情况,但它看起来杂乱无章,不准确 (更不用说了)。特别是,不精确性是一个问题,因为整个点是要得到精确的1:1的比率。(另外,我实际上并不关心缩放级别本身,只关心寻址本机像素。) 所以我的问题,从务实到哲学:Css <;帆布>;在本机分辨率下,尽管放大,视网膜,css,html,canvas,zooming,retina-display,Css,Html,Canvas,Zooming,Retina Display,所以我有一个元素,我在其中画东西。矢量化的东西,而不是像素推动。我想在最大范围的观看条件下,以最少的资源以最高的质量展示。具体来说,我希望确保画布像素和设备像素之间有1:1的映射,以消除模糊、耗时的像素缩放操作 有 我看过“视网膜”显示(结论:devicePixelRatio是你的朋友),但它们都假设在100%变焦下观看。同样地,我也看到过这方面的情况,但它看起来杂乱无章,不准确 (更不用说了)。特别是,不精确性是一个问题,因为整个点是要得到精确的1:1的比率。(另外,我实际上并不关心缩放级别本
在Firefox和Chrome的现代浏览器版本中,基本上无法检测缩放级别: 在Firefox 18+上,Mozilla更改了手动缩放时的devicePixelRatio值(cmd/ctrl+/-),从而无法知道浏览器是处于缩放模式还是视网膜设备,而忽略了设备这个词所代表的内容 在Chrome 27(意味着WebKit和Blink)上,webkitTextSizeAdjust在台式机版本的浏览器上被弃用。这是我所知道的唯一一种检测桌面chrome放大的防弹方法。 还有两种其他方法,但它们并没有涵盖所有的基础——一种使用SVG,但在iFrame中不起作用;另一种使用window.inner/outerWidth,并且在有侧边栏或DevTools打开时不起作用 我发现(对于Chrome和Internet Explorer),两者之间存在着非常微妙的差异
,以及canvas.width
canvas.style.width
画布
占据整个窗口
首先以逻辑像素(我称之为“CSS像素”)获取窗口的大小:
这些值以“逻辑像素”为单位。放大浏览器时,“逻辑像素”的数量会减少:
Zoom window.innerWidth x windows.innerHeight
==== ======================================
100% 1680 x 859
200% 840 x 448
400% 420 x 224
75% 2240 x 1193
然后你要做的是计算出窗口的“真实”大小;应用缩放校正因子。目前,我们将抽象出可以计算当前缩放级别的函数(使用TypeScript语法):
使用GetZoomLevel()
函数,我们可以计算窗口的实际大小,单位为“物理像素”。当我们需要将画布的宽度
和高度
设置为窗口大小(以物理像素为单位)时:
//set canvas resolution to that of real pixels
var newZoomLevel = GetZoomLevel();
myCanvas.width = styleWidth * newZoomLevel; //e.g. 1680. Not myCanvas.clientWidth
myCanvas.height = styleHeight * newZoomLevel; //e.g. 859. Not myCanvas.clientHeight
关键技巧是,画布将在内部渲染到一个大小为width
byheight
像素的曲面。渲染完成后,CSS可以出现并收缩或拉伸画布:
- 如果CSS使其变大,则使其模糊
- 如果CSS使像素数据变小,则丢弃像素数据李>
myCanvas.style.width = styleWidth + "px"; //e.g. "420px"
myCanvas.style.height = styleHeight + "px"; //e.g. "224px"
因此,画布将在浏览器窗口中正确定位和调整大小,但内部使用完整的“真实”像素分辨率
GetZoomLevel()
是的,您需要缺少的片段,GetZoomLevel
。不幸的是,只有IE提供信息。同样,使用TypeScript表示法:
function GetZoomLevel(): number {
/*
Windows 7, running at 131 dpi (136% zoom = 131 / 96)
Internet Explorer's "default" zoom (pressing Ctrl+0) is 136%; matching the system DPI
screen.deviceYDPI: 130
screen.systemYDPI: 131
screen.logicalYDPI: 96
Set IE Zoom to 150%
screen.deviceYDPI: 144
screen.systemYDPI: 131
screen.logicalYDPI: 96
So a user running their system at 131 dpi, with IE at "normal" zoom,
and a user running their system at 96 dpi, with IE at 136% zoom,
both need to see the same thing; everything zoomed in from our default, assumed, 96dpi.
http://msdn.microsoft.com/en-us/library/cc849094(v=vs.85).aspx
Also note that the onresize event is triggered upon change of zoom factor, therefore you should make sure
that any code that takes into account DPI is executed when the onresize event is triggered, as well.
http://htmldoodads.appspot.com/dimensions.html
*/
var zoomLevel: number;
//If the browser supports the corrent API, then use that
if (screen && screen.deviceXDPI && screen.logicalXDPI)
{
//IE6 and above
zoomLevel = (screen.deviceYDPI / screen.logicalYDPI);
else
{
//Chrome (see http://htmldoodads.appspot.com/dimensions.html)
zoomLevel = window.outerWidth / window.innerWidth; //e.g. 1680 / 420
}
return zoomLevel;
}
不幸的是,除了IE支持之外,没有浏览器告诉您:
- 设备dpi
- 逻辑dpi
function OnWindowResize() {
if (drawingTool == null)
return;
//Zoom changes trigger window resize event
//get size in CSS pixels (i.e. 96 dpi)
var styleWidth = window.innerWidth; //myCanvas.clientWidth;
var styleHeight = window.innerHeight; //myCanvas.clientHeight;
var newZoomLevel = GetZoomLevel();
// myCanvas.width = document.body.clientWidth;
// myCanvas.height = document.body.clientHeight;
//set canvas resolution to that of real pixels
myCanvas.width = styleWidth * newZoomLevel;
myCanvas.height = styleHeight * newZoomLevel;
//myCanvas.clientWidth = styleWidth;
//myCanvas.clientHeight = styleHeight;
myCanvas.style.width = styleWidth + "px"; //styleWidth.toString() + "px";
myCanvas.style.height = styleHeight + "px"; //styleHeight.toString() + "px";
drawingTool.Width = myCanvas.width;
drawingTool.Height = myCanvas.height;
// Only take action if zoom factor has changed (won't be triggered by actual resize of window)
if (newZoomLevel != lastZoomLevel) {
lastZoomLevel = newZoomLevel;
drawingTool.CurrentScaleFactor = newZoomLevel;
}
}
告诉图形代码用户当前的缩放级别也很重要,以防您试图硬编码任何长度。例如,试图画画
(50,50)处的32px盒
这是错误的。你需要画一张画
128像素盒at(200200)
当缩放因子为4时
注意:任何代码都会发布到公共域中。无需归因
我知道这一点。那是在公园里。也就是说,我不理解对devicePixelRatio缩放的憎恨。当然,这使得确定缩放变得困难,但是由于缩放不是这里真正的问题,并且这种行为使得现有的视网膜感知的画布代码只是在缩放下工作(模必须检查DeVeleXelelRead改变大小调整事件),我认为这是一件好事。显然,Chrome 31也将实现这一点。不过,将这种行为带到所有Firefox、Chrome、Opera和IE上,或者至少一年前是这样。这一切可能归结于一个简单的原因——可用性。放大/缩小的方式
function GetZoomLevel(): number {
/*
Windows 7, running at 131 dpi (136% zoom = 131 / 96)
Internet Explorer's "default" zoom (pressing Ctrl+0) is 136%; matching the system DPI
screen.deviceYDPI: 130
screen.systemYDPI: 131
screen.logicalYDPI: 96
Set IE Zoom to 150%
screen.deviceYDPI: 144
screen.systemYDPI: 131
screen.logicalYDPI: 96
So a user running their system at 131 dpi, with IE at "normal" zoom,
and a user running their system at 96 dpi, with IE at 136% zoom,
both need to see the same thing; everything zoomed in from our default, assumed, 96dpi.
http://msdn.microsoft.com/en-us/library/cc849094(v=vs.85).aspx
Also note that the onresize event is triggered upon change of zoom factor, therefore you should make sure
that any code that takes into account DPI is executed when the onresize event is triggered, as well.
http://htmldoodads.appspot.com/dimensions.html
*/
var zoomLevel: number;
//If the browser supports the corrent API, then use that
if (screen && screen.deviceXDPI && screen.logicalXDPI)
{
//IE6 and above
zoomLevel = (screen.deviceYDPI / screen.logicalYDPI);
else
{
//Chrome (see http://htmldoodads.appspot.com/dimensions.html)
zoomLevel = window.outerWidth / window.innerWidth; //e.g. 1680 / 420
}
return zoomLevel;
}
function OnWindowResize() {
if (drawingTool == null)
return;
//Zoom changes trigger window resize event
//get size in CSS pixels (i.e. 96 dpi)
var styleWidth = window.innerWidth; //myCanvas.clientWidth;
var styleHeight = window.innerHeight; //myCanvas.clientHeight;
var newZoomLevel = GetZoomLevel();
// myCanvas.width = document.body.clientWidth;
// myCanvas.height = document.body.clientHeight;
//set canvas resolution to that of real pixels
myCanvas.width = styleWidth * newZoomLevel;
myCanvas.height = styleHeight * newZoomLevel;
//myCanvas.clientWidth = styleWidth;
//myCanvas.clientHeight = styleHeight;
myCanvas.style.width = styleWidth + "px"; //styleWidth.toString() + "px";
myCanvas.style.height = styleHeight + "px"; //styleHeight.toString() + "px";
drawingTool.Width = myCanvas.width;
drawingTool.Height = myCanvas.height;
// Only take action if zoom factor has changed (won't be triggered by actual resize of window)
if (newZoomLevel != lastZoomLevel) {
lastZoomLevel = newZoomLevel;
drawingTool.CurrentScaleFactor = newZoomLevel;
}
}