1

我知道如何在 Vaadin 14.1 应用程序的屏幕上呈现 JPEG 图像。

特别是 3 行:

imageReader.setInput( imageInputStream ); // Render the image from the data provided by the `ImageInputStream`.
imageWidget.setWidth( imageReader.getWidth( 0 ) + "px" ); // Get the pixel size of the rendered image.
imageWidget.setHeight( imageReader.getHeight( 0 ) + "px" );

…这个的:

private Image createImageWidget ( String mimeType , String fileName , InputStream inputStreamOfImageData )
{
    if ( mimeType.startsWith( "image" ) )
    {
        Image imageWidget = new Image();
        try (
                inputStreamOfImageData ;
                // Auto-close.
        )
        {
            // Get the octets of the image data.
            final byte[] bytes = IOUtils.toByteArray( inputStreamOfImageData );

            // Make the image widget for Vaadin.
            imageWidget.getElement().setAttribute( "src" , new StreamResource( fileName , ( ) -> new ByteArrayInputStream( bytes ) ) );
            imageWidget.setAlt( "File name: " + fileName );

            // Size the image for display in the HTML/CSS for faster rendering without the page layout jumping around in front of user.
            try (
                    ImageInputStream imageInputStream = ImageIO.createImageInputStream( new ByteArrayInputStream( bytes ) ) ;
                    // Auto-close.
            )
            {
                // Apparently, image readers (parsers/decoders) are detected at runtime and loaded via the "Java Service Provider Interface (SPI)" facility.
                final Iterator < ImageReader > imageReaders = ImageIO.getImageReadersByMIMEType( UploadView.MIME_TYPE_JPEG );  // OR, for multiple image types, call `ImageIO.getImageReaders( in )`.
                if ( imageReaders.hasNext() )
                {
                    ImageReader imageReader = imageReaders.next();
                    try
                    {
                        imageReader.setInput( imageInputStream ); // Render the image from the data provided by the `ImageInputStream`.
                        imageWidget.setWidth( imageReader.getWidth( 0 ) + "px" ); // Get the pixel size of the rendered image.
                        imageWidget.setHeight( imageReader.getHeight( 0 ) + "px" );
                    }
                    finally
                    {
                        imageReader.dispose();
                    }
                } else
                {
                    throw new IllegalStateException( "Failed to find any image readers for JPEG. " + "Message # e91ce8e4-0bd3-424d-8f7c-b3f51c7ef827." );
                }
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
        return imageWidget;
    }
    // TODO: Log error. Should not reach this point.
    System.out.println( "BASIL - ERROR - Ended up with a null `imageWidget`. " + "Message # 415bd917-67e2-49c3-b39a-164b0f900a3a." );
    return null;
}

我知道在这 3 行中,我们是在通知网页图像的宽度和高度,而不是让网页在加载时发现图像的大小。这使得布局更快,并避免了网页在用户面前跳来跳去的烦恼。

➥ 我的问题是:对于具有高像素密度的现代显示器(Apple 称其为Retina显示器)呢?

如何让图像有效地显示其所有像素,但占用屏幕上的空间最少?

如果显示器具有老式的低像素密度,则图像应该显示更多厘米的物理屏幕空间,而不是高密度 Retina 显示器,在高密度 Retina 显示器上,图像可以占用更少厘米的屏幕,同时在技术上仍能显示图像的所有像素。

4

2 回答 2

2

在线快速搜索没有找到任何本机浏览器功能,可<img>根据本机像素密度为元素提供不同尺寸。我们所拥有的是window.devicePixelRatio可以使用 JavaScript 读取的属性。请参阅Mozilla 的指南

您可以通过两种不同的方式一起使用它executeJs- 动态设置每个元素的大小或将值获取到服务器,然后在服务器上为每个Image组件进行计算。

第一种选择看起来像这样:

imageWidget.getElement().executeJs("this.style.width = ($0 / window.devicePixelRatio) + 'px';" +
    "this.style.height = ($1 / window.devicePixelRatio) + 'px';",
  imageWidth, imageHeight);

获取比率并使用它的第二种方法如下:

ui.getPage().executeJs("return window.devicePixelRatio;")
  .then(Double.class, ratio -> this.devicePixelRatio = ratio.doubleValue());

// Later, in some other location
imageWidget.setWidth((imageWidth / this.devicePixelRatio) + "px");
imageWidget.setHeight((imageHeight / this.devicePixelRatio) + "px");

编辑:第二种方法的变体,使用retrieveExtendedClientDetails而不是executeJs

ui.getPage().retrieveExtendedClientDetails(details -> this.devicePixelRatio = details.getDevicePixelRatio());

// Later, in some other location
imageWidget.setWidth((imageWidth / this.devicePixelRatio) + "px");
imageWidget.setHeight((imageHeight / this.devicePixelRatio) + "px");
于 2019-10-28T09:33:53.473 回答
1

在 Vaadin 14 中,Image组件只是 HTMLimg标签的表示。这应该意味着像 em 或相对百分比这样的大小单位应该适用。当您不想对屏幕尺寸做出假设时,这些应该会更好。创建响应式设计的一般经验法则是避免像素大小并使用例如 em 或百分比来代替。

但是,如果您出于某种原因想要自己执行相对大小计算,您可以通过以下方式获取浏览器窗口的大小:

    getUI().ifPresent(ui -> ui.getPage().retrieveExtendedClientDetails(receiver -> {
        int bodyWidth = receiver.getBodyClientWidth();
        System.out.println("Width "+bodyWidth);
    }));
于 2019-10-27T08:12:27.407 回答