Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Css <;帆布>;在本机分辨率下,尽管放大,视网膜_Css_Html_Canvas_Zooming_Retina Display - Fatal编程技术网

Css <;帆布>;在本机分辨率下,尽管放大,视网膜

Css <;帆布>;在本机分辨率下,尽管放大,视网膜,css,html,canvas,zooming,retina-display,Css,Html,Canvas,Zooming,Retina Display,所以我有一个元素,我在其中画东西。矢量化的东西,而不是像素推动。我想在最大范围的观看条件下,以最少的资源以最高的质量展示。具体来说,我希望确保画布像素和设备像素之间有1:1的映射,以消除模糊、耗时的像素缩放操作 有 我看过“视网膜”显示(结论:devicePixelRatio是你的朋友),但它们都假设在100%变焦下观看。同样地,我也看到过这方面的情况,但它看起来杂乱无章,不准确 (更不用说了)。特别是,不精确性是一个问题,因为整个点是要得到精确的1:1的比率。(另外,我实际上并不关心缩放级别本

所以我有一个元素,我在其中画东西。矢量化的东西,而不是像素推动。我想在最大范围的观看条件下,以最少的资源以最高的质量展示。具体来说,我希望确保画布像素和设备像素之间有1:1的映射,以消除模糊、耗时的像素缩放操作

有 我看过“视网膜”显示(结论:devicePixelRatio是你的朋友),但它们都假设在100%变焦下观看。同样地,我也看到过这方面的情况,但它看起来杂乱无章,不准确 (更不用说了)。特别是,不精确性是一个问题,因为整个点是要得到精确的1:1的比率。(另外,我实际上并不关心缩放级别本身,只关心寻址本机像素。)

所以我的问题,从务实到哲学:

  • 在现代(=过去6个月发布的)浏览器中,获得1:1画布的首选方式是什么?我真的需要检测设备像素比率和变焦(包括检查变焦变化)并从中计算吗

  • 如果我不关心资源消耗,那么2:1画布(视网膜显示器上的本机分辨率,其他地方的放大率高达200%)值得考虑吗?我认为缩小规模比扩大规模好

  • 浏览器供应商对此有何看法?是否正在研究更好的解决方案?或者缩放是他们认为web开发人员不需要担心的一个细节?部分回答:很多人认为这很重要。对于DeVeleXelelRe比率是否应该随着缩放级别而改变,或者是否允许用户指定的变焦检测以及特定于设备的DPI检测是前进的方向。[

  • ]似乎有些犹豫。
  • 有多少人经常浏览网站!100%变焦?他们中有多少人使用高DPI显示器?有统计数据吗?[答:大约10%的gmail用户。]


  • 在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
    它们不能互换。如果你想操纵它们,你必须非常小心地去实现你想要的。某些值以物理像素为单位进行测量。其他的是以逻辑像素(如果屏幕仍然缩放到96 dpi,则为像素)测量的

    在我的例子中,我希望
    画布
    占据整个窗口

    首先以逻辑像素(我称之为“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
    by
    height
    像素的曲面。渲染完成后,CSS可以出现并收缩或拉伸画布:

    • 如果CSS使其变大,则使其模糊
    • 如果CSS使像素数据变小,则丢弃像素数据
    最后一步是使用CSSlengthString,调整画布大小,使其占据整个客户端区域窗口:

    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
    我的完整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像素盒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;
        }
    }