我发现(对于 Chrome 和 Internet Explorer)是非常棘手、微妙的区别
canvas.width
, 和
canvas.style.width
它们不可互换。如果你想操纵它们,你必须非常小心地这样做才能达到你想要的。有些值是以物理像素为单位测量的。其他的以逻辑像素(如果屏幕仍缩放到 96 dpi 时的像素)来衡量。
就我而言,我希望Canvas
占据整个窗口。
首先获取以逻辑像素为单位的窗口大小(我称之为“CSS 像素”):
//get size in CSS pixels (i.e. 96 dpi)
var styleWidth = window.innerWidth; //e.g. 420. Not document.body.clientWidth
var styleHeight = window.innerHeight; //e.g. 224. Not document.body.clientHeight
这些值以“逻辑像素”为单位。当我的浏览器放大时,“逻辑像素”的数量会减少:
Zoom window.innerWidth x windows.innerHeight
==== ======================================
100% 1680 x 859
200% 840 x 448
400% 420 x 224
75% 2240 x 1193
然后你要做的是找出窗口的“真实”大小;应用缩放校正因子。目前,我们将抽象出可以计算当前缩放级别的函数(使用 TypeScript 语法):
function GetZoomLevel(): number
{
}
使用该GetZoomLevel()
函数,我们可以计算窗口的实际大小,以“物理像素”为单位。当我们需要将画布的width
and设置为以物理像素为单位height
的窗口大小时:
//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
的表面。height
渲染完成后,CSS 可以出现并缩小或拉伸您的画布:
- 如果 CSS 使它变大,则模糊它
- 如果 CSS 使其更小,则丢弃像素数据。
最后一步是调整画布的大小,使其占据整个客户区窗口,使用CSS长度String:
myCanvas.style.width = styleWidth + "px"; //e.g. "420px"
myCanvas.style.height = styleHeight + "px"; //e.g. "224px"
因此画布将在您的浏览器窗口中正确定位和调整大小,但在内部使用完整的“真实”像素分辨率。
获取缩放级别()
是的,您需要缺少的部分,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 之外没有其他浏览器支持告诉你:
我的完整 TS 代码是:
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 像素框在 (200,200)
当缩放系数为 4 时。
注意:任何代码都会发布到公共领域。无需归属。