Giter Site home page Giter Site logo

blog's Introduction

Airpub logo

Airpub NPM version

Airpub 是基于 Angular.js 搭建,多说 数据驱动的纯前端写作工具。

基于多说现有社交网络账户体系与健壮 API,Airpub 能够托管在任何静态资源服务器上,例如 GitHub Pages、又拍云储存、七牛云储存或使用自定义的 FTP 工具上传到任何 VPS 或虚拟主机中使用,为最终用户提供便捷流畅,优质轻量的博客写作与阅读体验。访问官方网站

快速开始

Airpub 功能特色


已实现或基本实现的功能与 Roadmap:

  • 支持 Markdown 写作
  • 支持图片上传,目前支持上传到 又拍云
  • 支持插入代码以及代码高亮
  • 支持基于多说的社交网络账户登录
  • 基于 Angular Directive 规范的 add-on 系统
  • 基于 bower 管理的主题系统
  • 符合规范的,更好的 Angular SEO 实现

即将实现或计划中的功能:

  • 基于 Airpub 的多 编辑/作者 实现
  • 更好的移动端登录体验:去掉多说登录页面跳转,直接跳转到相应社交网站登录页面

如何安装


自动安装

使用 Airpub CLI Installer 来安装 Airpub 的稳定版本:

$ [sudo] npm install -g airpub-installer

新建站点目录:

$ mkdir my-airpub-blog && cd my-airpub-blog

然后执行操作将相关的依赖全部安装完毕:

$ airpub install

airpub installer 将自动新建配置,仅需简单编辑

$ vi configs.js

大功告成!即可访问你的站点,开始 Airpub 简洁流畅的书写体验。

手动安装

手动安装 Airpub 也异常简单,仅需使用 Git 拉取主干代码,即可直接部署在静态资源服务器上:

// 拉取代码
$ git clone https://github.com/turingou/airpub.git

// 手动新建配置文件
$ cd airpub
$ cp configs-sample.js configs.js

// 根据提示编辑配置文件,填入多说配置与站点信息
$ vi configs.js

配置填写完毕后,我们需要安装 Airpub 依赖的前端资源文件,执行:

$ bower install 

依赖安装完成后,即可访问你的站点,开始 Airpub 简洁流畅的书写体验。

配置指南


Airpub 仅需简单配置,即可达成不错的写作与阅读效果。在 configs.js 中,你应该会注意到存在两种配置项:

  • airpubConfig: Airpub 博客系统本身的配置,包括站点名称,描述,以及其他元数据。

    • name: 站点名称
    • description: 站点描述
    • url: 线上访问地址,必须是绝对地址,用于分享
    • upyun 又拍云配置(用于上传图片)
      • bucket: 又拍云 bucket 名称
      • form_api_secret: 又拍云 form_api_secret 必选
      • host: 返回的图片的默认主机地址(可选
      • endpoint: 默认 API 地址(可选)
  • duoshuoQuery: 你的多说站点信息,目前仅需要提供 short_name

Airpub 鉴权基于多说用户系统,这意味着你不需要对 管理员 身份进行任何配置,仅需使用生成该 short_name 相应的多说用户登录即可进行文章的新建与管理操作。

重要提示: 如你的多说 short_name 之前有在任何服务中使用过,请申请全新的多说站点以获得不同的 short_name,我们推荐你采用这样的方式来管理自己不同的多说站点之间的关系,例如 myname-wordpressmyname-airpub

重要提示: 建议你在多说管理后台(站点管理 => 设置 => 文章信息来源)开启 只接受来自服务器的文章信息请求 选项,防止非 API 请求造成的非法数据写入。

提示: 由于表单上传会暴露您的 form_api_secret,建议开启防盗链模式,并经常性更换 form_api_secret

开发指南


Airpub 的前端依赖基于 bower 构建,工作流基于 NPM 构建。在进行 Airpub 二次开发之前,确保你有安装 Node.js、NPM 以及 bower,然后执行以下步骤:

$ cd airpub
$ bower install 
$ npm install
$ npm run dev

命令 $ npm run dev 将再 localhost:3000 运行一个静态资源服务器,并实时压缩 dist 文件。需要确保这个端口没有被占用后再执行此操作。

贡献代码


欢迎为 Airpub 贡献代码。如果你有兴趣为 Airpub 贡献代码,请先查阅本项目中的相关代码,fork 项目后,再提交 pull request。 如果你对 Airpub 计划中的主题系统或 add-on 系统感兴趣,欢迎在 issue 区提交新话题。

MIT license

Copyright (c) 2014 Guo Yu <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


docor generated using docor @ 0.1.0. brought to you by turingou

blog's People

Contributors

xiangpaopao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blog's Issues

让Storyboard控制更多的样式!

作为iOS中的新技术,Storyboard(以下简称SB)的优点和缺点同样明显,关于纯手写和StoryBoard间的博弈,推荐阅读一下 http://onevcat.com/2013/12/code-vs-xib-vs-storyboard/ 。而本文主要是要讲如何在SB中控制更多的样式。

作为一个web前端开发者,习惯了使用灵活的HTML+CSS控制页面,做iOS开发时,要创建大量类、写大量代码来构建视图,有时还不得不和业务代码混在一起,这一点很不爽。之前在SB上做过一些尝试,但是SB上提供的选项实在不够用,比如想给一个按钮设置圆角都没有选项,以往我都是创建一个新类,写了一行代码:btn.layer.cornerRadius = 10; 直到我在objc.io上看到了这篇文章 Behaviors in iOS Apps,才明白原来可以通过User Defined Runtime Attributrs 来给视图修改样式。例如我需要给button设置圆角,那就添加一条layer.cornerRadius 并填上合适的值。

st1

button

自定义属性支持以下数据类型

  • Boolean
  • Number
  • String
  • Localized String
  • Point
  • Size
  • Rect
  • Range
  • Color
  • Nil

OK,我们来尝试给按钮添加边框

image

问题来了,按钮怎么也不显示边框。原因是layer的borderColor属性类型是CGColor而不是Color,所以我们得转换,可以通过创建一个Category来让把Color转换为CGColor

CALayer+XibConfiguration.h

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CALayer(XibConfiguration)
@property(nonatomic, assign) UIColor* borderColorFromUIColor;
@property(nonatomic, assign) UIColor* shadowColorFromUIColor;
@end

CALayer+XibConfiguration.m

#import "CALayer+XibConfiguration.h"

@implementation CALayer(XibConfiguration)
-(UIColor*)borderColorFromUIColor
{
    return [UIColor colorWithCGColor:self.borderColor];
}
-(UIColor*)shadowColorFromUIColor
{
    return [UIColor colorWithCGColor:self.shadowColor];
}
-(void)setBorderColorFromUIColor:(UIColor*)color
{
    self.borderColor = color.CGColor;
}
-(void)setShadowColorFromUIColor:(UIColor*)color
{
    self.shadowColor = color.CGColor;
}
@end

然后把刚才的borderColor替换为borderColorFromUIColor重新运行代码,发现边框正常显示了。
button2

那如果只需要四边边框宽度不一样怎么办呢?CSS中我们是这样写的border-width: 5px 10px 2px 10px;,为了iOS中也能这样写,我写了一个方法来实现。

-(NSString*)borderWidths
{
    return self.borderWidths;
}
-(void)setBorderWidths:(NSString*)borderWidths
{
    NSString *widthsStr = [[borderWidths stringByReplacingOccurrencesOfString:@"{" withString:@""]
                           stringByReplacingOccurrencesOfString:@"}" withString:@""];
    //widths:[top,right,bottom,left]
    NSArray *widths = [widthsStr componentsSeparatedByString:@","];
    float topWidth = [[widths objectAtIndex:0] floatValue];
    float rightWidth = [[widths objectAtIndex:1] floatValue];
    float bottomWidth = [[widths objectAtIndex:2] floatValue];
    float leftWidth = [[widths objectAtIndex:3] floatValue];

    if (topWidth!=0) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = self.borderColor;
        border.frame = CGRectMake(0, 0, self.frame.size.width, topWidth);
        [self addSublayer:border];
    }
    if (rightWidth!=0) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = self.borderColor;
        border.frame = CGRectMake(self.frame.size.width - rightWidth, 0, rightWidth, self.frame.size.height);
        [self addSublayer:border];
    }
    if (bottomWidth!=0) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = self.borderColor;
        border.frame = CGRectMake(0, self.frame.size.height - bottomWidth, self.frame.size.width, bottomWidth);
        [self addSublayer:border];
    }
    if (leftWidth!=0) {
        CALayer *border = [CALayer layer];
        border.backgroundColor = self.borderColor;
        border.frame = CGRectMake(0, 0, leftWidth, self.frame.size.height);
        [self addSublayer:border];
    }
}

把他添加到CALayer+XibConfiguration.m就可以在SB中通过layer.borderWidths来设置不同宽度的边框了。

这里我只是提供了这个思路,类似的还有很多样式都可以通过这种方式控制,减少代码量。刚才的demo可以从 https://github.com/xiangpaopao/ChangeStyleInSB 获取。

settings

ios

移动端Web上传图片实践

从iOS 6+、Android 3+开始 (来源http://mobilehtml5.org/),移动端可以通过网页中的<input type="file">来拍照上传或是上传相册中的照片。 不过从图片上传到服务器后可能会遇到图片莫名其妙旋转的问题,如图

default

一些设备在拍照时明明是竖着拍的(右),传到服务端后从图片查看器中看到的是横着的(左),而在一些图片处理工具或是浏览器中通过http协议看到的却是正常的,原因是在照片的exif中的Orientation属性控制了照片的旋转方向。

//Exif 信息示例
Exif.Image.Make                              Ascii       6  Canon
Exif.Image.Model                             Ascii      20  Canon PowerShot S40
Exif.Image.Orientation                       Short       1  top, left
Exif.Image.XResolution                       Rational    1  180
Exif.Image.YResolution                       Rational    1  180
Exif.Image.ResolutionUnit                    Short       1  inch
Exif.Image.DateTime                          Ascii      20  2003:12:14 12:01:44
Exif.Image.YCbCrPositioning                  Short       1  Centered
......

大部分图片查看器和编辑工具都会去根据这个属性控制照片方向,而windows自带的查看器等工具并不理睬他。
为什么要有Orientation属性呢,我并没有找到官方的解释,见到种说法挺有道理:几乎所有的摄像头在出场的时候成相芯片都是有方向的,拍出来的照片的像素都是默认方向的。如果每拍一张照片就对这些像素进行旋转,如果数码相机每秒连拍20张来算,旋转操作将会非常耗时。更聪明的做法是拍照时只记录一个方向,然后显示的时候按方向显示出来即可。因此exif定义了一个标准的方向参数,只要读图的软件都来遵守规则,加载时候读取图片方向,然后做相应的旋转即可。这样既可以达到快速成像的目的,又能达到正确的显示。

orient_flag2

修正图片方向的问题

为了图片显示不出问题,我们得修改Orientation属性。首先想到的是服务端来修正方案,对于图片来说exif信息不是必须的,可以根据Orientation的值来对照片进行手动矫正的操作,然后再去掉exif,类似这样:

switch(exif['Orientation']){
    case 2:
        image->save;
        break;
    case 3:
        image->rotate(-180)->save;
        break;
    case 4:
        image->rotate(180)->save;
        break;
    ······
}

更好的方式是用一些图片工具自动处理,GraphicsMagick和Imagemagick用来处理这个再合适不过了,他俩都可以用对图像进行旋转、裁剪、缩放、替换颜色;添加文本、水印、图形等常见操作,GraphicsMagick是从Imagemagick分支出来的,他俩有着几乎一样的API,可以在命令行工具中轻松操作。这里我用的是GraphicsMagick,他更轻便,易装易用。在Java、PHP、Nodejs等常见后端语言中可以用相关库轻松的操作GraphicsMagick的API。

后端以Nodejs为例。首先你需要在你的机器上安装GraphicsMagick。 然后npm install gm 模块就可以了。gm提供的接口非常友好,你只要

gm('/path/to/img.jpg')
.autoOrient()
.resize(240, 240)
.write('/path/to/new.jpg', function (err) {
  if (err) ...
})

这样就已经完成了图片的自动修正方向和压缩尺寸的工作。

异步上传图片

传统提交表单方式放在今天已经不能忍了,XHR2中支持把文件放在Formdata对象中异步提交,只考虑移动端,就可以舍弃iframe之类的兼容方案了。核心代码这样:

var xhr = new XMLHttpRequest();
var formData = new FormData();
formData.append('file', input.files[0]);
xhr.open('POST', form.action);
xhr.send(formData);

XHR2中还可以通过process事件来监听进度,实现类似进度条的功能

xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
function updateProgress(event) {
    if (event.lengthComputable) {
        var percentComplete = event.loaded / event.total;
    ......
  }
}

用FormData发送的请求头中你的Content-Type 会变成这样 multipart/form-data; boundary=----WebKitFormBoundaryyqVkWF3PcCpAzZp9,如果上传时要附带参数也可以直接append到formData里。
然后Nodejs中可以用connect-busboy来接收文件,在express框架中大概是这样:

var express = require('express'),
    http = require('http'),
    fs = require('fs'),
    busboy = require('connect-busboy'),
    gm = require('gm');

var app = express();
app.use(busboy());
.....
app.post('/upload', function(req, res) {
    req.busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
        ......
        file.on('end', function () {
            gm(filePath)
                .autoOrient()
                .thumbnail(200, 200)
                .write(fullname, function(err){
                    if (err) return console.dir(arguments)
                    res.json({
                    ......
                    });
                }
            )
        });
        file.pipe(fs.createWriteStream(filePath));
    });
    req.pipe(req.busboy);
});
......
app.listen(3001);

前端压缩图片

图片上传的主体工作算是完成了,不过现在手机随便拍张照片就是一两兆,wifi环境下不说,移动网络通过这方案上传照片就有点坑了。手机客户端中一般会先压缩图片再上传,Web中如何实现压缩后上传呢?
可以把图片读到canvas中,然后用canvas.toDataURL()接口输出画布的base64编码,再把base64编码转成Blob塞到Formdata里传到后端。这样即可以压缩图片减少流量,又可以在前端就修正图片旋转的问题。(Discuss:直接把base64传到后端是否可行呢,后面试一试)

canvasResize这个库已经把一切封装好了https://github.com/gokercebeci/canvasResize ,同时他依赖Exif.js 修正了因Orientation属性产生的旋转问题。前端主要的代码:

var file = input.files[0];
canvasResize(file, {
        width: 300,
        height: 0,
        crop: false,
        quality: 100,
        callback: function(data, width, height) {
            var blob = canvasResize('dataURLtoBlob', data);
            var form = new FormData();
            form.append('file',blob);
            $.ajax({
                type: 'POST',
                url: server,
                data: form,
                contentType: false,
                processData: false,
            }).done(function (res) {
                ......
            }).fail(function () {
                ......
            }).always(function () {
                ......
            });
        }
});

Nodejs中代码可以参考前面的,继续用connect-busboy模块接收文件。

实际测试一下iOS没问题,Android 4 有些机型不行,貌似修改过file的Blob数据发到服务端的数据字节就会为0 这是安卓的bug https://code.google.com/p/android/issues/detail?id=39882 。 网上有人给出的解决方案是用FileReader把文件读出来,然后把整个二进制文件当请求发到服务端,这种方式要附带参数的话只能放url里了。

var reader = new FileReader();
reader.onload = function() {
    $.ajax({
                type: 'POST',
                url: server,
                data: this.result,
                contentType: false,
                processData: false,
                beforeSend: function (xhr) {
                    xhr.overrideMimeType('application/octet-stream');
            },
            }).done(function (res) {
                ......
            }).fail(function () {
                ......
            }).always(function () {
                ......
            });
};
reader.readAsArrayBuffer(file);

后端在接收这些数据时,会是一段一段的,我是用的拼接的方式处理

app.post('/upload', function(req, res) {
    var imagedata = '';
    req.setEncoding('binary');
    req.on('data', function (chunk) {
        imagedata += chunk
    });
    req.on('end', function (chunk) {
        fs.writeFile(filePath, imagedata, 'binary', function(err){
            if (err) throw err
            res.json({
            ......
            });
        })
    });
});

实测一下,稍低端的的安卓上有点卡,毕竟处理一张图片的运算量可不小,目测目前用前端压缩上传方案的不多,至少微博触屏版 (http://m.weibo.cn/) 就是把原始图片直接上传的,这种方式是否适合直接使用或者还有哪些可以优化的地方有待验证。

这里有一个完整的demo https://github.com/xiangpaopao/mobile-upload-demo 包括上面提到的两种方案
使用的话,依次安装GraphicsMagick > npm install > node app.js

参考

Follow the Step-by-Step Guide to Claim Your Tokens! 📌

Introduction:

Welcome to the exciting world of crypto airdrops! Here's a curated list of active airdrops that you wouldn't want to miss. Dive in and explore the opportunities:

📌 Follow the Step-by-Step Guide to Claim Your Tokens!

  1. Share on Social Media:

    🚀 Claim Your Share: Pyth Network Airdrop 🚀 Unlock the potential of $PYTH tokens in this step-by-step guide. Claim yours now! Share on Twitter

    — Pyth Network (@pythnetwork) November 28, 2023
  2. Verify Eligibility:
    After sharing and connecting your walle

Active Airdrops:

  1. Layer Zero Airdrop

    Layer Zero Banner
  2. Pyth Network Airdrop

    Pyth Network Banner
  3. Mantle Network Airdrop

    Mantle Network Banner

(译)比较CSS与JS的动画性能

原文地址:http://davidwalsh.name/css-js-animation

基于JavaScript的动画性能竟然达到甚至超过了CSS transtions动画? Adobe和Google不断发布web App是打算挑战native App?

本文一步一步的诠释了基于JavaScript DOM的动画库(例如Velocity.js与GSAP)为何会比基于jQuery或CSS的动画库有更好的性能。

jQuery

首先,不要把JavaScript和jQuery错误的混为一谈。 jQuery展示动画会比原生JavaScript慢。 原因是尽管jQuery非常强大,但是他的目标从来不是成为一个高性能的动画引擎。

  • 由于jQuery提供了多种动画接口,所以无法避免布局抖动的问题。
  • jQuery的内存消耗频会繁触发垃圾回收机制,造成动画丢帧的问题。
  • jQuery为了保护其自身的动画机制,使用setInterval取代requestAnimationFrame.

小节:布局抖动发生在动画初始阶段,动画运行阶段js的垃圾回收会造成卡顿,而用动画帧频低是因为没有使用RAF。

实例

如何避免由DOM查询和DOM更新而引起的布局抖动。

var currentTop,
    currentLeft;

/* 产生布局抖动 */
currentTop = element.style.top; /* 查询 */
element.style.top = currentTop + 1; /* 更新 */

currentLeft = element.style.left; /* 查询 */
element.style.left = currentLeft + 1; /* 更新 */

/* 不产生布局抖动 */
currentTop = element.style.top; /* 查询 */
currentLeft = element.style.left; /* 更新 */

element.style.top = currentTop + 1; /* 更新 */
element.style.left = currentLeft + 1; /* 更新 */

查询会迫使浏览器在更新完页面后重新计算页面样式(同时考虑到新的更新的影响)。 由此产生的开销对动画运行的影响至少是16ms。

使用RAF接口并不需对现有的库进行重构。 让我们来比较一下RAF与setInterval的基础用法:

var startingTop = 0;

/* setInterval:为了达到60fps把间隔设为16ms   (1000ms/60 ~= 16ms). */
setInterval(function() {
    /* 因为此处每秒执行60次,所以我们将top属性的增量设置为1/60秒 */
    element.style.top = (startingTop += 1/60);
}, 16);

/* requestAnimationFrame: 当浏览器处于正常时,尝试以60fps运行 */
function tick () {
    element.style.top = (startingTop += 1/60);
}

window.requestAnimationFrame(tick);

结论:使用RFA会以很少的代码改动量获取更高的动画性能

CSS Transitions

CSS Transitions超越了jQuery卸载动画逻辑到浏览器本身,这有效地

1.通过优化DOM操作和内存消耗来避免卡顿;

2.使用底层的RAF机制

3.强制硬件加速(利用GPU的能力来提高动画表现)。

然而事实上,JavaScript本身也能实现这些优化。 并且GSAP一直就是这么做的。 新型动画引擎Velocity.js,在现有的技术上又进一步优化,这个我们待会讨论。

由此可见,通过对程序的改进,Javascript动画是可以和CSS动画相提并论的。 并且JavaScript动画实际上可以比他们快。

让我们思考一下CSS动画库的缺点

  • Transitions强制硬件加速消耗了GPU的资源,在高负荷的情况下导致卡顿。 这在移动设备上表现的更为明显。 (具体来说,浏览器主线程与排版线程之间数据传输时占用系统开销会造成卡顿。 一些CSS属性(如transforms和opacity)不受此种系统开销影响)。 Adobe在这里阐述了这个问题。
  • IE10以下不支持transitions,导致使用IE8和IE9来访问桌面站点很受欢迎。
  • 因为transitions不由JavaScript原生控制(JavaScript仅仅是触发他们),浏览器不知道如何通过JavaScript来优化他们。

相反:基于JavaScript动画库可以自己决定何时启用硬件加速,他们支持各版本的IE,并且他们非常适合批量优化动画。

我建议只有当你是为了移动开发并且动画只包含简单的状态变化时才使用原始的CSS transitions。 在这种情况下,transitions是一个高性能的原生解决方案,允许你保留所有动画逻辑在样式表内,从而避免使用JavaScript库。 然而,如果你在设计复杂UI或正在开发一个有多种状态UI的应用程序,总得使用一个动画库来确保你的动画性能和工作流程仍是可控的。有一个管理CSS transitions很棒的库 Transit

JavaScript动画

好吧,既然说JavaScript性能可以占据上风,那么到底快多少呢? 快到足够创建一个能与WebGL相媲美的3D动画示例;快到足够创建一个你认为要使用Flash或者After Effects才能制作出来的超炫片头。快到足够创建一个你以为canvas才能实现的虚拟世界

下面比较一下主流动画库的性能,包括Transit(使用了CSS transitions),在Velocity文档的顶部 VelocityJS.org

问题来了:通过什么标准来判断JavaScript的性能呢? 下面列举了基于Javascript的动画可以优化的要素:

  • 同步DOM→整个动画序列减少布局抖动。
  • 缓存属性值,以减少发生DOM查询(这是DOM动画性能上的致命弱点)。
  • 在相同的兄弟元素调用时缓存单元单位(例如将px 转换为%、em等)。
  • 跳过将要变为不可见的元素的样式更新。

回顾下我们之前讨论的关于布局的问题,Velocity.js利用这些最佳实践来缓存重用一个动画的最终值的起始值的动画,从而避免一开始就查询DOM元素的值:

$element
    /* 将元素滑到视图的下面 */
    .velocity({ opacity: 1, top: "50%" })
    /* 延迟1000ms后将元素滑到到视图之外 */
    .velocity({ opacity: 0, top: "-50%" }, { delay: 1000 });

在上面的例子中,第二此调用Velocity时自动使用opacity:1与top:50%作为初始值。

浏览器可能最终会对一些相同的事情进行优化,但这样做会减少动画代码量以方便开发人员。 因此,出于同样的原因,jQuery不使用RAF(见上),浏览器不会为了优化而对这种机制有任何干扰。

最后,让我们来比较一下这两个JavaScript动画库(Velocity.js和GSAP)。

  • GSAP是一个高性能、功能丰富的动画引擎。 Velocity是一个轻量级UI动画工具,大大提高性能和工作流程。
  • GSAP需要商业授权。 Velocity是基于ultra-permissive MIT许可免费开源的。
  • GSAP和Velocity在实际项目中的表现难以分出高低。

我的建议当你需要精确控制时间(如重新映射、暂停/恢复/寻求)、动作(如bezier曲线路径),或复杂的分组/排序时使用GSAP。 这些特性对于游戏开发和某些领域的应用程序至关重要,但是对于web应用程序的UI就不那么重要了。

Velocity.js

GSAP的功能丰富并不意味着Velocity自身的功能弱。 相反,Velocity不仅包含了jQuery的$.animate()的所有功能 ,而且还集成了颜色动画, transforms, 循环, easings, 类动画, 滚动动画。所有的这一切,压缩后仅仅只有7KB

简而言之,Velocity相当于是把jQuery,jQuery UI,和CSS transitions结合了起来。

此外,从使用的角度来看,Velocity使用了jQuery的$.queue()方法,从而与jQuery的$.animate() , $.fade() ,$.delay() 功能无缝结合。由于Velocity的语法与$.animate() 是相同的, 所以你不需要改变你页面中的代码 。

先让我们来初步了解一下 Velocity.js 与 $.animate()的相同点 :

$element
    .delay(1000)
    /* 用Velocity控制元素的向上运动持续2000ms */
    .velocity({ top: "50%" }, 2000)
    /* 当元素向上运动的动作完成后 使用jQuery自带的方法使元素淡出 */
    .fadeOut(1000);

进一步,可以创建一个3D滚动的动画场景也只是两个简单的代码:

$element
    /* 在1000ms内将浏览器滚动到元素的上方 */
    .velocity("scroll", 1000)
    /* 然后使元素沿着他的Y轴旋转360度 */
    .velocity({ rotateY: "360deg" }, 1000);

总结

Velocity的理念是在DOM动画方面高性能、简单易用。本文侧重点是前者,在 VelocityJS.org 的头部可以更多地了解后者。

在我们结束之前,记住这一点:一个高性能的UI不仅仅需要选择正确的动画库,更重要的是优化你的页面。 你可以总谷歌的分享会中学到更多关于这些:

像图片一样布局

移动端经常会有这样的展示页面,页面中有一些独立的元素,并且伴随各种交互效果、转场动画。

img img

针对页面布局的话,大概有这样的需求:

  • 不滚动页面,所有元素均在一屏之类展示
  • 像图片那样缩放元素---宽度改变时高度按比例变化
  • 背景图需要把浏览器窗口撑满
  • 往往项目是独立的,需要快速上线,开发周期短

这种形式页面在正常的文档流中布局显然不太合适,比较传统的做法是这样:

  • 布局以绝对定位为主
  • 用百分比配合px控制宽高、位置
  • 背景图用background-size:cover撑满
  • 用css媒体查询来适应多种屏幕
  • css搞不定的请js帮忙

布局一个单屏展示页

比如这样一个640*960的设计稿,分背景和按钮两层,要求背景全屏(可以不显示全)按钮定位在精确的位置上。

img

传统做法

一般会把背景图用background-size:cover显示在一个宽高撑满屏幕的容器上以适应各种屏幕, 这个按钮怎么定位呢,一般是会这样做吧position:absolute;bottom:18%;

模拟一下iPhone5微信中的显示
img

iPhone4微信中的显示
img

可以看到iPhone4中按钮错位,原因是当屏幕尺寸改变时,背景图与按钮的尺寸与位置会遵循不同的规则变化。这个例子中的效果貌似还能接受,可有些场景对定位的要求可能比这更高。

解决这个问题一般会用媒体查询针对屏幕做适配吧

@media screen and (max-height: 500px) {
  .btn{
    bottom:12%;
  }
}

Demo 在这里 http://jsbin.com/zugape/edit

如果页面中元素多、定位要求精确,这种做法是比较暴力的。下面是支付宝十年晒单页面中针对不同尺寸屏幕做的适配

/* <=640 */
@media screen and (min-width: 319px) and (max-width: 321px) {
    ...
}
/* 720 */
@media screen and (min-width: 359px) and (max-width: 361px) {
    ...
}
/* 1024*768, 2056*1536 */
@media screen and (min-width: 383px) and (max-width: 385px) {
    ...
}
/* 800 */
@media screen and (min-width: 399px) and (max-width: 401px) {
    ...
}
/* 1080 */
@media screen and (min-width: 539px) and (max-width: 541px) {
    ...
}
/* 1200 */
@media screen and (min-width: 599px) and (max-width: 601px) {
    ...
}
/* 1440 */
@media screen and (min-width: 719px) and (max-width: 721px) {
    ...
}
/* 1600 */
@media screen and (min-width: 799px) and (max-width: 801px) {
    ...
}
/* for small screen */
@media screen and (max-height: 500px) {
    ...
}
/* for iPhone6 Plus */
@media only screen and (device-width: 414px) and (-webkit-min-device-pixel-ratio: 3),
only screen and (device-width: 375px) and (-webkit-min-device-pixel-ratio: 3){
    ...
}

总结下这种方式的缺点:

  • 要把设计稿中的PX在大脑中换算成%
  • 百分比控制宽高是相对于父元素,计算繁琐
  • 用媒体查询针对各种尺寸的屏幕做兼容工作繁琐

图片的自适应规则

一张图片如果给他设置<img src="pic" style="max-width: 100%;max-height:100%” />的话,无论视口大小,他都会显示在视口里面,如图
img img

类似的还有图片作为背景显示时的background-size属性。
background-size: contain:缩放图像的最大值,其宽度和高度都能放入内容区域
img

background-size: cover:缩放图像的最小值,其宽度和高度都能放入内容区域
img

当你改变图片的宽度或高度时,图片的另一边会自动按比例缩放,如果div有这种能力多好啊!

vw、vh--为移动而生

vw、vh是CSS3中出现的新的长度单位,vw 相对于视窗的宽度,视窗宽度是100vw;vh 相对于视窗的高度,视窗高度是100vh。
其中视窗指的是浏览器实际显示区域,即window.innerWidth/window.innerHeight的大小。
如 想一个元素的宽是视口宽的一半,只需设置width:50vw

与百分比的异同

乍一看好像和百分比类似,并没发现多少优势,在进行一些尝试之后我总结了一下他们的异同

百分比 vw、vh
相对父级元素 相对视口
横向/纵向相对父级横向/纵向 vw/vh相对视口宽/高(即写vh就是相对视口高、写vw就是相对视口宽,不必横向与横向纵向与纵向对应)
对字体大小无效 对字体大小有效

Tips:其实margin-top/bottom以百分比为单位时他的参照对象并不是父元素的height而是width。详情阅读 doyoe margin系列文章

这些特性可以实现一些之前用CSS难以解决的问题。

相对视口100%高度

由于百分比高度是相对父级的,之前如果想让文档流中的某容器相对视口高度100%,只用css的话得从html>body>element一层层下来都设置height:100%,而现在只需给元素设置height:100vh
height 100% Demo http://jsbin.com/risegu/edit

响应式文字 && 像图片一样布局

先上Demo
百分比方式 http://jsbin.com/vemudo/edit
vw方式 http://jsbin.com/huwido/edit
这两个Demo建议把浏览器模拟成移动设备的样子,拉伸浏览器窗口宽度观察效果。

img img

可以看到当浏览器宽度改变时,百分比Demo中只有元素的宽度发生了变化,而统一使用vw做单位的Demo中文字的大小、元素的高度与宽度均按缩放比例发生了变化,这正是我们想要的“像图片一样布局”的效果。

vmin 与 vmax

还有vw、vh延生出来的单位vmin、vmax。
vmin:关于视口高度和宽度两者的最小值
vmax:关于视口高度和宽度两者的最大值

我觉得这是一组神奇的单位,但是暂时对这个使用场景的理解有限,能想到的场景是一个正方形,height:100vmin;width:100vmin时,得到的是这个视口中能显示满的一个最大正方形(http://jsbin.com/baheko);height:100vmax;width:100vmax时得到的是能把这个视口全部显示满的最小正方形(http://jsbin.com/tamasi)。

然后在codepen上找到这样一个demo,他让16:9的视频窗口在视口中自适应 http://codepen.io/CreativeJuiz/pen/KzkgL

其他适用场景有待发掘

vw、vh的问题

vw vh 在桌面端浏览器兼容性已经是比较好了,不过在移动端貌似还需要等待,国产安卓浏览器的话UC到现在都不支持真不让人省心。
img

另外对张鑫旭的视区相关单位vw, vh..简介以及可实际应用场景 中他的结论:vw vh只适用于非定位元素;vh高度值的内部元素不支持百分比%高度 有些疑问,我在测试中并未发现这样的情况,这篇文章写于2012年,不知道是不是这样的情况只发生在当时的浏览器。Demo http://jsbin.com/dineka/edit

rem方案

回头来看我们的布局,vw vh的方案因为兼容性问题只能放弃,重新分析下我们的需求:
其实我们需要那么一个全局的相对单位...
我们可以通过修改这个单位来控制整个布局...
我们可以通过判断屏幕的比例来缩放整个页面以展示全部内容...

然后想到类似手机淘宝的动态rem的方案:所有布局元素单位使用rem,由于rem是相对于根元素的,所以不同屏幕按一定规则控制的font-size 即可兼容各屏幕。

var root = document.getElementsByTagName('html')[0],
    NATIVE_W = 640;
function updateSize() {
    var w = window.innerWidth;
    var cw = w / (NATIVE_W / 100);  
    root.style.fontSize = cw + 'px';
}
window.onload = updateSize;
window.onresize = updateSize;

这样的页面一般会有设计稿的,我们需要设置rem和设计稿中px的转换比例。
1rem = 1px 这样固然方便,但是有些浏览器有最小字体的限制。
所以我想让 1rem = 100px。
我们的设计稿一般为640 x 960,这个尺寸是针对iPhone4,设备像素比是2,那么我们实际需要html的font-size为50px。
这样的话假如设计稿中一个元素尺寸为240px x 200px,
那么这个元素需要在屏宽为320px的设备上显示的尺寸是120px x 100px,而我们需要他在布局时设置的宽高是2.4rem x 2rem。
设计稿宽640px 也就是整个页面应为 6.4rem。 所以对应不同宽度的设备时用window.innerWidth(视口宽) / 6.4 得到的就是对应此设备的font-size。
布局时,把设计稿上的尺寸除以100然后把px单位换成rem。

怎么解决比较短的屏幕显示不完全的情况呢,可以先判断一下视口的比例,当视口高宽比低于设计稿宽高比时,缩小html节点的font-size这样就能把内容显示全了

var root = document.getElementsByTagName('html')[0],
    NATIVE_W = 640,
    NATIVE_H = 960;

function htmlSize() {
    var cw = 50,
        w = window.innerWidth,
        h = window.innerHeight;  
    if ((w / h) > (NATIVE_W / NATIVE_H)) {
        cw = h / (NATIVE_H / 100);
    } else {
        cw = w / (NATIVE_W / 100);
    }
    root.style.fontSize = cw + 'px';
}
window.onload = htmlSize;
window.onresize = htmlSize;

Demo http://jsbin.com/rupole/edit
可以试下缩小、拉大窗口布局也会像图片那样相应变化,并且无论窗口是什么样的尺寸,元素都会出现在比较合理的位置,当然,一些特殊情况仍然要用媒体查询来适配。

然后在布局时,其实只要把这段js放在页面中,就rem当成px来用就行了,不需要多考虑啥,这个方案的优点就是构建页面成本低,跨屏显示效果也能满意。

calc

另外有些元素我们想他垂直方向上针对中心定位而不是顶部或底部,比如想让一个小球居中之前大概是这样:

#cir{
  width:200px;
  height:200px;
  border-radius:100px;
  background:#888;
  position:absolute;
  left:50%;
  top:50%;
  margin-left:-100px;
  margin-top:-100px;
}

其实CSS3中有这样一个表达式:calc()(CSS里居然有这玩意,我第一次看到时怀疑是不是SASS或LESS里的),他可以给元素的border、margin、pading、font-size和width等属性动态计算值,例如:top:calc(50% - 1rem),这在这种展示页面的布局中是相当有用的,上面的css可以改写成:

#cir{
  width:200px;
  height:200px;
  border-radius:100px;
  background:#888;
  position:absolute;
  left:calc(50% - 100px);
  top:calc(50% - 100px);
}

Demo http://jsbin.com/gasato/edit

关于更多calc的介绍建议阅读大漠的这篇博文 http://www.w3cplus.com/css3/how-to-use-css3-calc-function.html

遗憾的是这玩意在桌面端浏览器中支持的已经比较好了,不过在移动端的表现令人堪忧,安卓原生浏览器从4.4开始支持,而最新版的安卓UC仍然不支持。

img

前端技能之切图

为何会有此文

Web界面构建过程中,切图是常是必不可少的一步,我认为做好这个工作需要做到:

  • 清楚的知道需要切出什么样的图
  • 熟悉一款图像处理的工具

剩下的基本就是体力活了。很多团队是没有“页面重构师”这一职位的,有时会把切图任务分配给UI设计师,而由于构建出某种样式界面的方法也多样的、并且大部分设计师没有界面开发经验,所以设计师往往不明确究竟要切出什么样的图,这一点在移动端体现的更为明显。

例如设计稿中有这样一个按钮:背景为有描边的圆角矩形,按钮上有一个icon和文字。大家在构建UI时会如何实现呢。

image

我想到的几种方法:

  • 直接切出包含所有信息的一张图片

  • 切出可伸缩的背景图,通过代码自动伸缩,然后切出icon 并打上文字

    背景图和icon: image   image

    (为了能看清icon 我把透明的背景填充成了灰色)

  • 通过代码绘制出背景、圆角、描边样式,icon采用图标字体 (关于图标字体,可以了解一下 http://iconfont.cn/ http://fontawesome.io/这两个项目)

暂且不讨论各种方法的优劣,在实际项目中三种方式都会有人使用,恐怕很多设计师是不了解UI构建中这些细节的,这就需要工程师和设计师描述清楚每一张图的需求,增加了沟通成本,切图稍有不慎会影响显示效果。

相比而言,我认为工程师自己学习一下图像工具的使用可以达到事半功倍的效果,于是便有了此文。

第一次写技术博客,受限于本人水平,有写的不如意的地方还请见谅和指正,本文适合不太会切图的工程师们阅读。

PS中相关功能

关于切图的工具,这里我们使用Photoshop(以下以Photoshop CC版本为例,不同版本可能存在一些差异),因为他更灵活、适用场景更广。
介绍一下使用PS切图时常用到的功能:
首先是图像菜单中的命令

image

图像>图像大小

这个好理解,就是修改图像的尺寸

image

需要注意的就是 一般情况下,为防止图像调整尺寸时失真,我![image]们会锁定宽高比(图中锁的按钮),另外用于屏幕上显示的图像分辨率一般设为72。想了解更多关于图像和分辨率知识 建议阅读 http://helpx.adobe.com/cn/photoshop/using/image-size-resolution.html

图像>画布大小

画布大小是图像的完全可编辑区域。好比你在一张纸上作画,发现纸张不够大时,可以通过这个选项来扩大可绘区域。

例如,下面200 * 200的图像中心有一个圆,当我把画布大小调整后,图像大小变为300 * 200,而图像中的圆的尺寸并未发生变化。你可以通过“定位”来编辑新画布的位置。

image   image

image

图像>裁剪

这条命令用来从图像中裁剪出所需部分。
使用方法:用选区工具从图像中选出要保留的部分,执行“图像”>“裁剪”命令。

image

image

image

图像>裁切

常用于移去图像中不需要的透明区域。如下图,透明的背景上有一个球,画布的大小比球所需的区域大得多,使用“图像”>“裁切”命令可以得到非透明像素的最小区域图像。

image

image

image

通过勾选“顶”、“底”、“左”、“右”可以选择需要修正的区域。

该命令同样适用于非透明背景的图像,选择“左上角像素颜色”或“右下角像素颜色”可从图像中移去左上角或右下角像素颜色的区域。

再看到工具栏中切图相关的工具:

image

裁剪工具

image 裁剪工具的使用和“图像>裁剪”命令类似。
选择裁剪工具后,可以在图像中框选出一块区域,双击后图像会移去未选中的区域。

image

在框选过程中可以通过工具栏中的参数来限定区域。如限定宽高、限定宽高比。

image

切片工具&&切片选择工具

而在实际项目中,往往遇到的是一整个设计稿中有大量图片需要切出来,这就需要用到切片工具了。
选择切片工具image可以在图像中划分出若干个区域,如下图:

image

蓝色标注的区域我我划分出的切片,灰色标注的为PS自动产生的切片。

使用image可以编辑已经划分出的切片,你可以调整他的位置、大小和对齐。如需更精准的控制你的切片,可以右击该切片在“切片选项”中通过数值设置。“名称”选项既输出图片的文件名。

image

文件>存储为 Web 和设备所用格式

调整好图像,就可以开始输出了,使用“存储为 Web 和设备所用格式”命令,可以得到更优化、更适合用于构建UI的图片。执行该命令后可以对文件的格式、压缩率等参数进行配置。(想了解关于格式,推荐阅读一下这篇博文 http://ued.taobao.org/blog/2010/12/jpg_png/)如果图像中包含切片,你可以选取你所需要输出的切片,也可以选择输出用户切片或者全部切片。

image

切图实战

我使用了来自freewebsitetemplates.com的素材用来演示一下切图,你可以从 http://www.freewebsitetemplates.com/preview/zerotype/获取到该素材。下面介绍一下我常使用的三种切图方法,仅以素材中的首页做个示范。
打开下载到的资源,可以看到里面有一个PSD文件及若干html文件,打开PSD文件,分析下,大概有这几个地方需要输出切图:

image

普通切图法

普通切图方法就是使用切片工具&&切片选择工具,在设计稿上调整好切片然后输出。

下面开始划分出我们需要的切片(注意:设计稿中已经包含原作者留下的切片,为防干扰最好使用切片选择工具把这些切片删除)。早期的浏览器对含透明通道的PNG图支持不好,所以处理含透明通道的图时我们一般使用GIF,或者索性把图形连同背景合并到一起输出不透明的图。而随着前端技术的发展和古老浏览器的淘汰,现在更好的做法是使用透明通道的PNG图片,既保证了图像质量又保证了图片在不同页面中都能适应。

要输出透明的切图,我们需要把PS中显示背景的图层隐藏。找这些填充背景的图层,点击“小眼睛”隐藏图层(图层是PS中比较重要的概念,建议阅读http://helpx.adobe.com/content/help/cn/photoshop/topics/layers.html了解更多)。

image

页面上这个按钮的处理,为了页面的可读性和图片能复用,我们只需要背景,所以也把文字隐藏。

现在手中的设计稿应该变成这个样子了

image

可以输出切图了,使用“文件>存储为 Web 和设备所用格式”命令,简单配置一下图片选项,然后选择一个路径,保存“所有用户切片”。

image

还没完,为了更好的体验,网页中的按钮是需要有悬停效果的,有经验的设计师早就准备好了,只不过这些效果的图层没有显示。找到并显示这个图层:

image

再次使用“文件>存储为 Web 和设备所用格式”命令,不过这次我们只要存这一张图就行了,在“存储为 Web 和设备所用格式”对话框中使用切片选择工具选中改切片,然后保存“选中的切片”。

image

文艺切图法

可以看到,普通切图法需要手动编辑切片,耗时耗力,当设计稿元素较多时容易出错。其实在处理大量图片时,我们常用到PS的脚本功能来对图像进行批处理,切图这一工作也可以通过脚本来实现半自动化。PS中预置了一些脚本,你也可以自己录制脚本,例如有时需要把一批大尺寸的图按比例转换成小尺寸图,就可以通过脚本来实现。(想更多了解PS中脚本功能 建议阅读 http://helpx.adobe.com/content/help/cn/photoshop/topics/automation.html

“文件>脚本>将图层导出到文件”这条命令是PS中预置的一个脚本,正如你想要的,他会把设计稿中的图层输出成图片。用这种方式切图,为了不破坏设计稿、脚本运行速度更快,我建议新建一个文档来进行。

新建一个尺寸为800*800的文档,把需要切图的元素拖动到这个文档中来,位置随意摆放,因为这个脚本会将“图层导出到文件”,所以有些元素可能包含多个图层的要使用“图层>合并图层”将他们合并。你现在的文档和图层管理器应该是这样的:

image

image

执行“文件>脚本>将图层导出到文件”

image

ok,在PS自动执行一系列操作后,就得到所有的切图了。

2B切图法

2B切图法就是使用裁剪工具,将设计稿中的每个元素分别提取出来并单独存储,仅需要输出少量图片或是要对图像局部调整时才使用此方法。

后话

在我看来,切图本身并没有多少技术含量,但这个环节却经常出问题。经常见到设计师抱怨开发人员没能还原设计稿中的效果,其中一条重要原因就是:设计师不明确切图的所有需求,而工程师们又不会或不愿意自己切图。这就好多人共同开发产品时,前端和后端都各人自扫门前雪,这样工作是很难协作下去的。

Over!Thanks GitHub! Thanks Freewebsitetemplates!

移动浏览器中的那些尺寸

做移动端页面开发时,时常想获取一下浏览器尺寸啥的,一直对移动端screen接口把握不准,网上能看到的资料也不多,打算把这些内容整理了一下。

回顾桌面上的那些东西

首先回顾下在桌面浏览器中用到的接口,这里只是列出,具体了解建议阅读 CSSOM视图模式(CSSOM View Module)相关整理w3c关于Cssom的文档翻译

window的接口的扩展

window.screenX
window.screenY
window.scrollX
window.scrollY
window.screenLeft
window.screenTop
window.innerHeight
window.innerWidth
window.outerHeight
window.outerWidth
window.pageXOffset
window.pageYOffset

screen接口

screen.height
screen.width
screen.availHeight
screen.availWidth
screen.availLeft
screen.availTop

HTMLElement接口的扩展

document.body.clientTop
document.body.clientLeft
document.body.clientWidth
document.body.clientHeight
document.body.scrollWidth
document.body.scrollHeight
document.body.scrollTop
document.body.scrollLeft
document.body.offsetWidth
document.body.offsetHeight
document.body.offsetParent

移动端一些概念

viewport

做过移动网页开发的对viewport这个概念不会陌生,他最早是Mobile Safari提出来的,用来把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中。要了解更多可以阅读Mozilla 开发者博客上的 在移动浏览器中使用viewport元标签控制布局

devicePixelRatio

提到viewport自然要提到devicePixelRatio这个概念,即设备像素比(设备上物理像素与设备独立像素的比例),如devicePixelRatio为2时,就表示用4个物理像素来显示一个页面像素。在浏览器中可以用window.devicePixelRatio获取到设备像素比,早期显示器的设备像素比都为1,后来随着手机屏幕分辨率的提升为了不改变浏览阅读体验移动设备就诞生了设备像素比这个概念。这个比值现在可能的值有很多1、1.5、2、3 ... 并且一些其他设备如MacBook也开始使用Retina屏了。一些设备的屏幕参数可以参考 http://screensiz.es/

对移动端有意义的接口

由于这些接口有些不在标准中,各浏览器的理解与实现也不尽相同,加上移动设备屏幕的局限性,所以一些接口在移动端上并没有多少意义。为此我用了几台机器做了如下测试,测试用的 demo地址

iPhone5
iP5_safari iP5_wx

iP5_uc iP5_qq

iP5_chrome iP5_chrome

红米Note
hm hm_wx

hm_uc hm_chrome

hm_baidu hm_liebao

hm_360

三星Note2
Note2 Note2_wx

Note2_qq

Nexus4
Nexus4 Nexus4_wx

三星9100
9100 9100_wx

Nexus4_wx

华为G525
HWG525 HWG525_wx

HWG525_UC

可以看到 这些接口在iOS中的浏览器几乎没有兼容性问题,而安卓上的表现不太靠谱。

  • window.devicePixelRatio这个没多少异议,在写webapp时这也是个重要的参考参数。
  • window.innerHeight/window.innerWidth 是浏览器窗口的视口(viewport)高度/宽度,即去掉边框工具栏后实际显示区域,这个接口在iOS和安卓上的表现都很好。
  • window.outerWidth/window.outerHeight 是整个浏览器窗口的高度/宽度,包括工具栏啥的。iOS中获取到的值都为0,安卓中有些机型获取到的是设备尺寸有些机型获取到的是物理尺寸,因此此接口不靠谱。
  • window.screenX/window.screenY/window.screenLeft/window.screenTop 用来得到浏览器顶部距离系统左上角的距离。iOS中此接口返回值为0,而安卓中通过window.screenY/window.screenTop得到的值各种情况都有,有些是0有些是titlebar的高度,有些是statusbar + titlebar的高度....而且有些单位是设备尺寸有些是物理尺寸....
  • screen.height/screen.width 得到的是屏幕高/宽,在iOS中得到的是设备尺寸,这样乘以一个devicePixelRatio就能得到物理分辨率。而安卓中也是存在有些机型获取到的是设备尺寸有些机型获取到的是物理尺寸的问题,红米Note中百度浏览器screen.height返回的竟然是721...呵呵
  • screen.availHeight/screen.availWidth 是屏幕可用尺寸。具体设备上的表现和上条类似,不想说了。
  • 最后测试的document.body.xxx 都是属于HTMLElement接口的扩展,经测试,用法与表现与桌面上类似,具体用法有疑问还是阅读 CSSOM视图模式(CSSOM View Module)相关整理

总结下,移动端屏幕/窗口接口中唯独靠谱的就是 window.innerHeight/window.innerWidth 了,好在还有这个可以用...

window

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.