前端圈

分享与交流前端开发相关知识

Web应用程序:编写一次代码,可在任何地方运行

本文介绍如何使用JavaScript构建响应式网站。

如果您使用Google的“响应式设计”,则会发现很多有关媒体查询的信息,这似乎是创建可在从智能手机到4k显示器的任何屏幕上运行的产品的首选方式。但是,我觉得在许多情况下,这是避免实际问题(这是数学之一)的笨拙,过于复杂的方法。让我解释。

Web App是看起来像常规应用程序的单个网页。交付给浏览器的代码既可以在服务器上生成,也可以在浏览器本身中生成,但是无论哪种方式,它都将包含许多JavaScript以提供用户体验。处理响应式设计所需的其他代码相当有限,因此让我们看看它是如何工作的。

看一下下面的Web应用程序,该应用程序始终垂直填充浏览器客户端区域,而无需任何滚动条(滚动在内容面板中完成)。它尝试保持特定的纵横比,并具有一组可选的背景图像,以提供内容的框架。可以在此处看到实时应用程序。

《Web应用程序:编写一次代码,可在任何地方运行》

我们首先创建一个主题描述符;一个名为的JSON文件theme.json,它定义了一些内容:

{
    "aspect-w":4,
    "aspect-h":3,
    "border":10,
    "font-scale":35
}

aspect-w并且aspect-h是所希望的纵横比的宽度和高度的部件,如前面所述。您可以使用4:3(如上所述),16:9或其他方式。

border是框架图形中左(或右)边框的宽度,以图像宽度的百分比表示。可能需要反复试验才能找到最佳值。

font-scale是一个值,它定义了适合内容高度的文本行数。它的值通常在30到40之间,其中前者会比后者大一些,并且实际上只能通过实验来选择它,因为它对不同的浏览器会产生不同的影响。

您看到的图形框架也是主题包的一部分。它包含帧中间,顶部和底部的图像,这些图像使用绝对定位,因此可以正确地彼此重叠。当屏幕调整大小时,顶部和底部将保持固定,而中间部分会自行调整以填充窗口的高度。

在您的JavaScript代码中,为window.resize事件设置处理程序:

window.addEventListener('resize', function() {      
    // Respond to the event by calling SetStyles below
});

现在进行计算。我将以看似伪代码的形式呈现此内容,但实际上它是一个子例程,是上述应用程序的生产代码的一部分。整个网站的脚本不到500行,包括空格和注释,但不包括用户内容(该内容取自Markdown文件),使用的语言是EasyCoder,这是一种基于浏览器的Javascript引擎,可以在飞然后跑他们。

变量的某些目的很明显,例如处理屏幕上的按钮,都带有大写字母。其他所有内容都是该语言语法的一部分。我添加了额外的注释来解释每个变量的用途以及计算的逻辑。请特别注意该语言直接设置DOM元素的CSS样式的方式;没有HTML,也没有虚拟DOM。cat,简称catenate,将一个字符串附加到另一个字符串。

!  Responsive design: Compute the size and position of all the screen elements

!  AspectW is the 'aspect-w' value from the theme descriptor
!  AspectH is the 'aspect-h' value from the theme descriptor
!  Border is the 'border' value from the theme descriptor
!  FontScale is the 'font-scale' value from the theme descriptor
!  Mobile is a flag that's true when the system has detected
!    we're using a smartphone in portrait mode

SetStyles:
!  Get the browser client dimensions
   put the width of window into WindowWidth
   put the height of window into WindowHeight

!  Choose an optimum width based on the window height and the requested aspect ratio
   put WindowHeight into Height
   multiply Height by AspectW giving Width
   divide Width by AspectH

!  Make sure the window is wide enough
   take Width from WindowWidth giving Margin
   divide Margin by 2
   if Margin is less than 0
   begin
      put 0 into Margin
      put WindowWidth into Width
   end

!  Style the Container (a DIV)
   set style `left` of Container to Margin cat `px`
   set style `top` of Container to 0
   set style `width` of Container to Width cat `px`
   set style `height` of Container to Height cat `px`

!  Style the background images (IMG elements).
!  There's a small fiddle in here to maintain a border at the bottom of the window
   set the style of MidImage to
      `position:absolute;left:0;top:0;width:` cat Width
      cat `px;height:` cat `calc(` cat Height cat `px - 2vh)`
   set the style of TopImage to
      `position:absolute;left:0;top:0;width:` cat Width cat `px`
   set the style of BottomImage to 
      `position:absolute;left0;bottom:2vh;width:` cat Width cat `px`

!  Get the width of the Content panel (a child of Container). Border is a percentage.
   multiply Width by Border giving Left
   divide Left by 100
   take Left from Width
   take Left from Width

!  Style the buttons at the top of the screen
   divide Width by 20 giving ButtonSize
!  If we are on a mobile device we need to make the buttons bigger
   if Mobile multiply ButtonSize by 2
   set style `position` of HomeButton to `absolute`
   set style `left` of HomeButton to 0
   set style `top` of HomeButton to 0
   set style `width` of HomeButton to ButtonSize cat `px`
   set style `height` of HomeButton to ButtonSize cat `px`

   multiply ButtonSize by 2 giving N
   set style `position` of BackButton to `absolute`
   set style `left` of BackButton to N
   set style `top` of BackButton to 0
   set style `width` of BackButton to ButtonSize cat `px`
   set style `height` of BackButton to ButtonSize cat `px`

   set style `position` of InfoButton to `absolute`
   set style `right` of InfoButton to 0
   set style `top` of InfoButton to 0
   set style `width` of InfoButton to ButtonSize cat `px`
   set style `height` of InfoButton to ButtonSize cat `px`

!  Compute the top and height of the content panel
   multiply Border by AspectW giving Top
   divide Top by AspectH
   take Top from Height giving Height
   take Top from Height

!  Style the content panel
   set the style of Content to
      `position:absolute;left:` cat Left cat `px;top:` cat Top cat `px;`
      cat `width:` cat Width cat `px;height:` cat Height cat `px`

!  Style the fonts at the top level (so the settings cascade)   
   divide Height by FontScale giving FontSize
   set style `font-size` of Container to FontSize cat `px`
   return

该算法从视口高度开始,从该视口高度计算与所需纵横比相对应的宽度。然后将其限制为不大于视口宽度,以确保其适合智能手机屏幕。

现在调整3帧图像的大小以适合计算的宽度。“中间”图像的大小也要适合视口高度。请注意,需要一个小提琴,否则,将略微裁切底部图像。不,我还不知道为什么。

接下来,确定“主页”,“返回”和“信息”按钮的大小。

接下来,使用主题描述符中给出的边框和外观值调整内容面板的大小。在调用此子例程之前,脚本已经为面板赋予了一种margin:0 auto样式,使其可以在窗口中居中放置。

最后,计算字体大小,作为视口高度的一部分。

调整窗口大小后,内容会立即平滑地进行调整以适应新的可用空间。这与媒体查询通常导致页面在从一种尺寸到另一种尺寸的每次转换中“跳转”的方式形成对比。

此处的代码可以轻松转换为JavaScript函数并集成到任何网页中;您只需要确保正确处理所有需要调整大小的元素即可。我之所以使用绝对定位,是因为需要保持浏览器面板的内容高度,也因为很容易从边缘定位组件。可以在折叠之下自由延伸的Web设计可以自然流动。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注