【问题标题】:GWT Canvas and Retina Display scaling issueGWT Canvas 和 Retina Display 缩放问题
【发布时间】:2017-10-30 16:26:11
【问题描述】:

我需要应用 GWT 和 html5 画布。由于 html5 画布完全被 gwt 包裹,我还希望我能够适应视网膜显示。

我搜索了互联网,但没有找到 GWT 的任何答案。因此,在 javascript 中执行此操作的常用方法是像这样设置比例因子Understanding HTML Retina Canvas Support

所以,我在我的 gwt 项目中尝试了同样的方法,结果是:

public void onModuleLoad() {

        Canvas canvas = Canvas.createIfSupported();
        canvas.getElement().setAttribute("width", "800");
        canvas.getElement().setAttribute("height", "500");
        canvas.getElement().getStyle().setProperty("border", "black solid 1px");
        RootPanel.get("root").add(canvas);

        Context2d ctx = canvas.getContext2d();

        //For Retina Displays
        int dpi = dpi();
        ctx.scale(dpi, dpi);

        double posX = 10;
        double posY = 10;
        double width = 200;
        double height = 30;
        double cornerRadius = 2;

        ctx.beginPath();
        ctx.moveTo(posX+(width/2), posY);
        ctx.arcTo(posX+width, posY, posX+width, posY+(height/2), cornerRadius);
        ctx.lineTo(posX+width, posY+(height/2));
        ctx.arcTo(posX+width, posY+height, posX+(width/2), posY+height, cornerRadius);
        ctx.lineTo(posX+(width/2), posY+height);
        ctx.arcTo(posX, posY+height, posX, posY+(height/2), cornerRadius);
        ctx.lineTo(posX, posY+(height/2));
        ctx.arcTo(posX, posY, posX+(width/2), posY, cornerRadius);
        ctx.lineTo(posX+(width/2), posY);
        ctx.setStrokeStyle("rgba(255,255,255,1.0");
        ctx.stroke();
        ctx.closePath();

        ctx.setShadowBlur(2);
        ctx.setShadowColor("rgba(0,0,0,0.5)");
        ctx.setShadowOffsetX(1);
        ctx.setShadowOffsetY(1);

        ctx.setFillStyle("white");
        ctx.fill();
    }


    public static native int dpi() /*-{
        //https://stackoverflow.com/questions/35820750/understanding-html-retina-canvas-support
        var ctx = $wnd.document.createElement("canvas").getContext("2d"),
        dpr = window.devicePixelRatio || 1,
        bsr = ctx.webkitBackingStorePixelRatio ||
              ctx.mozBackingStorePixelRatio ||
              ctx.msBackingStorePixelRatio ||
              ctx.oBackingStorePixelRatio ||
              ctx.backingStorePixelRatio || 1;

        return dpr / bsr;
    }-*/;

但是,它不起作用。相反,圆角矩形现在只是大小的两倍。平局看起来仍然很模糊。

如何调整画布以补偿视网膜显示器上的像素增加?

【问题讨论】:

    标签: canvas gwt retina-display


    【解决方案1】:

    好的,我找到了如何获得带有 GWT 和 Retina 显示屏的清晰画布。

    与上面的代码相同,但有以下变化:

    public void onModuleLoad() {
    
            int canvasWidth = 800;
            int canvasHeight = 500;
            Canvas canvas = Canvas.createIfSupported();
            canvas.setPixelSize(canvasWidth, canvasHeight);
            canvas.getElement().getStyle().setProperty("border", "black solid 1px");
            RootPanel.get("root").add(canvas);
    
            //In order to be sharp on a Retina Display, use the following code!
            Context2d ctx = createContext2DNatively(canvas.getElement(), canvasWidth, canvasHeight);
    
            //Continue as you would normally do...
    

    由于某种原因,我无法弄清楚如何在 GWT 中调整此选项。因此,我使用本机 Javascript 创建了它。该方法如下所示:

    public static native Context2d createContext2DNatively(Element canvas, int width, int height) /*-{
        //https://stackoverflow.com/questions/35820750/understanding-html-retina-canvas-support
        var ctx = canvas.getContext("2d"),
        dpr = window.devicePixelRatio || 1,
        bsr = ctx.webkitBackingStorePixelRatio ||
              ctx.mozBackingStorePixelRatio ||
              ctx.msBackingStorePixelRatio ||
              ctx.oBackingStorePixelRatio ||
              ctx.backingStorePixelRatio || 1;
    
        var ratio = dpr / bsr;
        canvas.setAttribute('width', width*ratio);
        canvas.setAttribute('height', height*ratio);
        ctx.scale(ratio, ratio);
        return ctx;
    }-*/;
    

    这应该可以解决问题。

    【讨论】:

    • 您似乎仍然缺少样式大小的更改 - 问题本身中的 setAttribute("width", "800") 代码可以被编辑为在 java 中传递 width*ratio 而不是等到 JSNI 方法。另外请记住,GWT3 将不支持 JSNI,与其现在编写新的 JSNI,不如编写 JsInterop。
    • 感谢您的提及。我实际上尝试过canvas.setAttribute("width", "800")。然而,这确实 - 令人惊讶的是 - 不起作用。因此它包含在 javascript 本机方法中。 BTW:样式大小设置在canvas.setPixelSize(canvasWidth, canvasHeight);
    • 嗯,很奇怪 - 它适用于我的项目,想知道这里有什么不同......很高兴你把它整理好了!
    猜你喜欢
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多