QQ Weather H5 フロントエンド完全分析_html/css_WEB-ITnose

WBOY
リリース: 2016-06-24 11:21:16
オリジナル
1101 人が閲覧しました

前書き: Mobile Q Weather とは

Mobile Q Weather は Mobile Q 6.0 以降の新機能で、このページにはその日の気温、5 日間の気温折れ線グラフ、および 24 時間の気温が表示されます。チャートなど また、インタラクティブな効果を高めるために、天気ページには 8 つの異なる天気情報に基づいて、対応する天気アニメーションが表示されます。雨、雪、浮遊雲、太陽光の点滅などのアニメーション効果。

モバイル QQ 天気を開発している間、私は多くのことを学び、書く価値のある場所がたくさんあることに気づきました。これが私の要約です。

1. REM の全体的なレイアウト

モバイル端末では、解像度の調整がよく問題になることがわかっています。デザイナーは、iPhone6 (750px) のビジュアル ドラフトを提供します。天気ページでは、全体のレイアウトに REM を使用する ことが非常に良い選択です。

rem

とは

rem (ルート要素のフォントサイズ) とは、ルート要素に対する相対的なフォントサイズの単位を指します。簡単に言えば、相対的な単位です。 rem 計算のルールは、ルート要素に依存することです。

基本的な書き方

以下に定義されているように、htmlのノードは以下のように定義されています

/*定义html根元素字体大小*/html{ font-size:10px;}/*定义子元素,采用rem作为单位*/.sonDom { width: 6rem; /*相当于 6*10=60px*/ height: 3rem; /*相当于 3*10=30px*/ line-height: 3rem; /*相当于 3*10=30px*/ font-size: 1.2rem; /*相当于 1.2*10=12px*/ border-radius: .5rem; /*相当于0.5*10=5px*/}
ログイン後にコピー

上記からもわかるように、remは実は費用対効果の単位に相当します

例えば、私たちが普段理解していることは 1 メートル = 10 デシメートル = 100 センチメートルです

同様に、次を取得できます: 1rem = ルート要素の font-size の値

ここで、HTML ルート要素の font-size は最初は 10px に設定されています。つまり、 1rem = 10px

上記より、

を渡すことができると結論付けることができます。 html の font-size 値を変更し、すべての要素を rem 単位を均等に使用して変更します。

そして、これはまさに完璧な解像度適応を達成するための rem の原理です。

ルート要素の font-size 値を動的に変更する方法

解像度適応を実現するには、画面のサイズに応じてルート要素の font-size 値を動的に計算する必要があります。 2 つの一般的な方法:

1. メディア クエリを使用する

メディア クエリを使用することで、ほとんどのシナリオに対応できます。考慮する必要があるのは、一般的に使用される画面幅だけです

/*默认为20px*/html { font-size : 20px;}/*判断宽度设置不同的html font-size值去覆盖默认值*/@media only screen and (min-width: 320px){    html { font-size: 10px; }}@media only screen and (min-width: 375){    html { font-size: 16; }}@media only screen and (min-width: 414px){    html { font-size: 20px; }}
ログイン後にコピー

2. js を使用して設定します

すべての画面サイズを考慮して、次のコードのように js を使用して計算することを検討してください (weather H5 も js を使用して変換します)。

 //设置fontsize   var doc = document,   win = window;   function initFontSize () {        var docEl = doc.documentElement,            resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',            recalc = function() {                var clientWidth = docEl.clientWidth; //window.innerWidth;                if (!clientWidth) return;                fontSizeRate = (clientWidth / 375);                var baseFontSize = 15 * fontSizeRate;                docEl.style.fontSize = baseFontSize + 'px';            };        recalc();        if (!doc.addEventListener) return;        win.addEventListener(resizeEvt, recalc, false);        doc.addEventListener('DOMContentLoaded', recalc, false);    };
ログイン後にコピー

rem 変換

開発中は、rem 変換を必要としないことがよくあります。たとえば、デザイン ドラフト ボタンが 120 ピクセルの場合、ルート ノードのフォント サイズは 14 ピクセルで、計算は 120/14 = 8.571 レムとなります。まだかなり面倒に感じますが、これらのタスクは sass およびその他のプリプロセッサ または build

を介して完了できます

たとえば、以下の Xiangshen によって作成された fis プラグイン

https://github.com/imweb/fis -parser- rem

レンダリング

以下に示すように、remの適応効果は非常に優れています

Remには注意が必要です

モバイル端末でremを使用する場合、互換性は問題ありません。ただし、注意が必要な点がいくつかあります:

1. 小数値の処理

ブラウザが異なると、rem から px の値を計算する場合、小数点以下の値の処理が異なります。

rem 計算の誤差の原因は次のとおりです。ブラウザのカーネル数値タイプの違い: ブラウザのカーネル数値タイプが float タイプの場合、小数点を含む値をより適切にサポートできます。ブラウザカーネルの数値型がint型で小数点をサポートしていない場合、数値が四捨五入されるため誤差が生じます。要素が大きいほど、偏差がより顕著になります。

2. スプライト画像 rem

スプライト画像を使用して rem を使用する場合、スプライト画像のアイコン間の距離が小さすぎる場合、px に変換された rem のサイズは厳密には正確ではないことがわかります。アイコンが境界を越えてしまう可能性があるため、画像間の間隔を大きくする必要があります。

3. 単純なレムでは適応性の高さの問題は解決されません。

単純な rem では身長適応の問題は解決されません。したがって、現時点では適応性の高いシナリオは多くありません。そのため、rem を使用して対応する身長適応を行う必要がある場合は、これを使用することをお勧めします。 La を支援する対応する js。

2. 柔軟なボックスの部分レイアウト

以前は、ページを均等にレイアウトする場合、次の方法がより一般的に使用されていたことがわかりました:

    float フローティング子要素を使用しますが、 float
    または サブ要素を inline-block に設定することですが、サブ要素のマージン値の設定に注意が必要です
css3 フレキシブル ボックス モデルを検討することもできるかもしれません。

互換性

驚くべきことに、現在主流のスマート モバイル デバイス オペレーティング システムである Android および iOS の組み込みブラウザも、それらを適切にサポートしていることです。これは、モバイル開発にとって、少なくともフロートとパディングを使用したくない私にとっては本当に素晴らしいことです。

モバイルQQ天気の使用

以下に示すように、div全体が5つの部分に分割され、各部分は同じ幅を占めます。

上記のHTML構造は次のとおりです

通过弹性盒子模型,设置其css代码如下:

/*设置容器为盒子*/.info-day-list { display: -webkit-box; padding: 1rem 0;}/*设置item*/.info-day-item { -webkit-box-flex: 1; /*设置item占据的比例*/ width: 1%; font-size: 1.4rem; line-height: 3rem; text-align: center;}
ログイン後にコピー

通过上面,可以发现,弹性盒子将模块的所拥有的空间进行我们自定义比例去分配。上面每个item设置的 box-flex 都为1,故其都有父容器 剩余空间 1比重的宽度。

需注意点

1、弹性盒子模型div块因为文字内容不同而不均分

在开发的时候,我发现在使用弹性盒子模型时,如果涉及到文字的时候需要注意

由于天气的描述文字长度不同,如西南风和微风,分别是三个字和两个字。会有不同的宽度而导致不均分

如上面css所示,我设置了子元素width为1%(只有设置了item是统一的width就行,不一定需要是1%)就可以解决这个问题

HTML5 canvas

我们可以看到在页面中带有温度折线图以及下雪下雨的动画,这个时候我们发现使用dom去绘制这样稍微复杂的动画时,性能并不好也不好操作。这时候我们可以考虑使用到HTML5的canvas画布去实现了。这样 可规避渲染树的计算,使渲染更快

由于代码比较篇幅较长,这里只给最终生成效果哈。

折线图表

下雨下雪动画

效果如下, 发现使用canvas在绘制这些动画的时候,还是十分方便的。

具体实现可以看下面这个文章 -前端如何呼风唤雨

canvas需注意点

1、canvas高清屏模糊

在绘制折线图的时候,我们发现,折线图在高清屏下十分模糊,这是为什么呢?

熟悉retina屏的同学应该都知道,在浏览器的window变量中有一个devicePixelRatio的属性,该属性决定了浏览器会用几个(通常是2个)像素点来渲染1个像素,举例来说,假设devicePixelRatio的值为2,一张100x100像素大小的图片,在retina屏幕下,会用2个像素点的宽度去渲染图片的1个像素点,因此该图片在retina屏幕上实际会占据200x200像素的空间,相当于图片被放大了一倍,因此图片会变得模糊。

因此我们的解决方案时: 更加屏幕像素比devicePixelRatio的小同比方法canvas

如下面代码

  //兼容高清屏幕,canvas画布像素也要相应改变  var c = document.getElementById("canvas");  //获取devicePixelRatio  var DPR = window.devicePixelRatio;画布宽高  //同比设置画板宽高  c.width = = canvasWidth * DPR;  c.height = canvasHeight * DPR;
ログイン後にコピー

2、内存占用

canvas对内存的消耗是挺大的,如非必要还是不要使用多个canvas

css3 transition animation

我们可以使用CSS3的transition和animation来实现许多交互效果。

使用transition实现滑动Slider

在天气内页有个星座slider,如下面

通过设置每个卡片的类名,使其切换不同的位置

.star-icon-outside-l { z-index: 20; -webkit-transform: translateX(-18.8rem) scale(.673); transform: translateX(-18.8rem) scale(.673);}.star-icon-outside-r { z-index: 20; -webkit-transform: translateX(8.5rem) scale(.673); transform: translateX(8.5rem) scale(.673);}.star-icon-beside-l { z-index: 40; -webkit-transform: translateX(-12.5rem) scale(.851); -webkit-transform: translateX(-12.5rem) scale(.851);}.star-icon-beside-r { z-index: 40; -webkit-transform: translateX(2.35rem) scale(.851); transform: translateX(2.35rem) scale(.851);}.star-icon-hide-l { z-index: 10; -webkit-transform: translateX(-25rem) scale(.673); transform: translateX(-25rem) scale(.673);}.star-icon-hide-r { z-index: 10; -webkit-transform: translateX(17rem) scale(.673); transform: translateX(17rem) scale(.673);}.star-icon-cur { z-index: 90; -webkit-transform: translateX(-5.05rem) scale(1); transform: translateX(-5.05rem) scale(1);}
ログイン後にコピー

animation循环动画

1、渐隐渐现

@-webkit-keyframes toggleShow{    0% { opacity: 0; }    11% { opacity: 0; }    12.5% { opacity: 1; }    20%{ opacity: 0; }    100%{ opacity: 0; }}
ログイン後にコピー

2、放大收缩

@-webkit-keyframes shine{    0% { -webkit-transform: scale(1,1); }    50% { -webkit-transform: scale(1.2,1.2); }    100% { -webkit-transform: scale(1,1); }}
ログイン後にコピー

3、飘动

@-webkit-keyframes moveToLeft /* Safari 和 Chrome */{    from {-webkit-transform: translate(0);}    to {-webkit-transform: translate(-33.33333333%);}}
ログイン後にコピー

优化

我们知道,在移动端开发,性能和加载速度是十分重要的,这里我们就需要考虑所有前端能优化的点,做好了优化, 才能时你这个页面更好的展示。以下是相关的优化内容

基本动画优化

基本的动画优化,如使用transform的translate来代替left等位移操作 3D加速等,

合理使用RAF(requestAnimationFrame)

使用raf能解决脚本问题引起的丢帧,卡顿问题,并且支持中间状态监听

//首页判断是否可以使用requestAnimFrame来替换setTimeoutwindow.requestAnimFrame =    window.requestAnimationFrame ||    window.webkitRequestAnimationFrame ||    function(callback) {        return window.setTimeout(callback, 1000 / 30);    };
ログイン後にコピー

canvas优化

使用canvas实现下雨下雪效果,是通过一帧一帧地去重绘下落的雨滴或者雪花。这里雪花雨滴越多,对手机的性能要求就越高。

因此我们需要对不同的手机进行处理,对于一些稍微低端的手机进行一些 降级处理和优化 。 根据渲染情况,相应的减少雨滴和雪花的个数,减少渲染计算时间

//判断每次update的时间差,如果发现时间长过长,则相应地减少动画的最大雪花个数 if (new Date - lastTime > 30 && drops.length < OPTS.maxNum && OPTS.maxNum > 21) {      OPTS.maxNum -= 10; }
ログイン後にコピー

内存优化

由于我们打开天气广告时,是新开一个webview的 因此我们需要暂停被遮住的天气webview的天气动画,减少内存消耗

if(mqq&&mqq.iOS&&mqq.addEventListener){      mqq.addEventListener("qbrowserVisibilityChange", function(e){          cancelAnimationFrame(drp_ticker);          if(!e.hidden){              update();          }      });  }
ログイン後にコピー

合理使用缓存

为了加快二次加载页面的速度,我们就需要使用好缓存。

天气的数据,都会用localstorage缓存起来

第二次短时间加载则会使用localstorage的数据,加快二次加载速度。

 //判断是否有可用的缓存if (checkCache('weather-local_weather_info')) {    //有则使用缓存    Page.processData(local_weather_info);    weather_info = local_weather_info;} else {    //没有缓存则去请求    Vinda.getData('data-weatherInfo', function(data) {        if (data && data.retcode == 0) {            Page.processData(data);            //将天气信息存储进来,新增时间戳,用于缓存新鲜度的判断            $.extend(data.result, {                searchTime: +Date.now(),                city: city            });            //每次获取都会更新缓存            $S.save({                key: 'local_weather_info',                value: data            });    });}
ログイン後にコピー

预加载

DNS预解析

我们可以通过dns 预解析prefetch,提前解析,减少dns请求时间

<link rel="dns-prefetch" href="//pub.idqqimg.com" />
ログイン後にコピー

CGI预加载

由于天气页面是强数据页面,对于cgi数据是强依赖的。因为提前预先加载cgi能够使我们更快地去渲染页面而不是等先拉取页面js再去执行页面js去请求cgi的这样的顺序。

代码优化

dom对象池复用

在天气内页有个星座slider,如下面

我们知道总共有12个星座,但我这里却只使用了7个dom(5个可见,2个分别是隐藏的),通过复用来实现循环的12个月。虽然这里并没有减少很多dom的数量,但我觉得dom对象池复用的思想能给多dom节点的的场景带来质的飞跃。

异步加载权重较低的模块

由于整个天气又有折线图,又有动画,又有下雨下雪等东西。因此我们需要对页面进行模块划分。每个部分都是一个模块 我i将天气页面大致分成下面几个模块

//页面总模块var Page = {/**/};//头部模块var headerMod = {/**/};//时间维度的温度变化图var timeDegreeMod = {/**/};//广告模块var adsMod = {/**/};//一周天气情况图var detailMod = {/**/};//天气动画模块var AnimationMod ={/**/}
ログイン後にコピー

然后通过总模块去管理子模块,由于模块的划分,我们可以很轻松的根据页面展示权重和先后顺序,分别去渲染和异步加载相应的模块

var Page = {    render: function(){        //渲染基本页面        headerMod.render();        timeDegreeMod.render();        detailMod.render();        //加载完天气信息才去加载广告;        adsMod.getAds();        //由于权重较低,因此异步加载下雨下雪的动画部分组件        require.async('./setAnimation', function(AMod) {            AnimationMod = AMod;            AnimationMod.init();        });    }}
ログイン後にコピー

其余基本优化

雪碧图,文件合并等减少请求数

资源压缩,代码压缩减少请求体积。

内联css, js置后等渲染无阻塞

兼容点

在开发手Q天气时,还遇到下面一些需要兼容和注意的点:

ios 广点通app广告处理逻辑兼容

由于手Q天气涉及到广告,大部分广点通广告是只需要点击链接跳转就可以了

但有些广告由于是app广告,需要引导用户去下载,故在ios上则需要做些兼容。在ios手机需要通过以下判断,改为呼起app store下载页面

  //判断是否为手Q打开且为ios且为app下载广告var isIosAppAds = mqq.iOS && mqq.device.isMobileQQ() && producttype == 19;//如果是app ios 广告,//则jsonp请求广点通给的跳转链接,获取跳转appstore的tencent串if (self.isIosAppAds) {    $.ajax({        url: adsMod.jump_url,        data: {            acttype: 1,        },        dataType: 'jsonp',        success: function(o) {            if (o && o.ret >= 0) {                var data = o.data || {};                if (data.dstlink) {                    //通过手Q接口呼起app                    mqq.app.launchApp({                        name: data.dstlink //self.dstlink                    });                }            }        }    });} else {    //默认打开新webview即可    mqq.ui.openUrl({        url: adsMod.jump_url,        target: 1,        style: 0    });}
ログイン後にコピー

X5内核兼容点

由于我们的场景是在手Q上打开,故需要兼容X5内核上的规范。

X5 tbs.1x版本时 ,伪元素是不能做动画的。

X5 tbs.1x版本时 ,不支持transition-timing-function 的ease-out曲线

目前了解,貌似到了X5 tbs.2x版本正在开始灰度支持。

更多x5上的问题,可以通过以下链接去查看QQ浏览器官网的 X5技术指南

非a标签跳转 bug

因为天气页面有许多跳转上报,需要先上报再跳转,然后我之前是这样写的

<div id="js-jump-xxx" onclick="reportAndJump();"></div>
ログイン後にコピー

但这样写发现在低版本的android机上,只能发起上报请求而不能进行链接跳转

后来经排查,发现低端android机只能使用a标签进行跳转操作

<a id="js-jump-xxx" onclick="reportAndJump();"></a>
ログイン後にコピー

不足

  • 由于页面涉及到比较多的动画和canvas,故对 内存的消耗比较高 ,这方面一直没有很好去解决低内存手机的内存消耗问题
  • 页面动画渲染和代码仍需雕琢。当时刚入职,许多方面还是一知半解。故自我觉得仍然有许多可以优化的地方。。。

总结

QQ天气H5是我毕业来到腾讯的第一个独立开发的项目。虽然现在已经交接了。但我时不时都会去看下这个项目的动态和代码提交记录。QQ天气H5这个项目,让我在刚入职时学会了许多。虽然写得并不是很好啦。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート