mobile web

improve-one-two-three

oUTLINE

  • Mobile Web & SPA
  • Frontend
    • JavaScript(Angularjs)
    • CSS(SCSS)、RWD
    • GPU rendering (x-scroll)
  • result

original

features

  • single page application
  • infinite scroll
  • history.pushstate(angular.route)

rotue

$routeProvider
    .when('/items/', {
        //首頁
        templateUrl: '/index',
        controller: 'indexCtrl'
    }).when('/item/:id?', {
        //商品頁
        templateUrl: '/item',
        controller: 'itemCtrl'
    }).when('/select/:id?', {
        //選擇頁(方案、付款方式)
        templateUrl: '/select',
        controller: 'selectCtrl'
    }).when('/detail/:id?', {
        //填寫詳細資訊
        templateUrl: '/detail',
        controller: 'detailCtrl'
    }).when('/success/:orderid?', {
        //訂購成功
        templateUrl: '/success',
        controller: 'successCtrl'
    })

infinite scroll

<div when-scrolled='loadMore()'>
    <div ng-repeat="item in items">
    ...
    </div>
</div>

directive whenScrolled

捲軸位置 > 元件高度 + 緩衝區

scope.apply(attr.whenScrolled)

 

 

Issue

  • infinite scroll 捲軸高度動態,換頁回覆麻煩

  • 維護手機版、電腦版功能重複(閹割版)

  • 純 CSS all in one(~2000 lines)

    • 修改困難

    • 無開發慣例,樣式無法重用

    • 各分站用 css 維護 theme(崩潰)

Solution

scroll、js、SASS

infinite list

infinite scroll

dom 過多越滾越慢

大列表問題(Ex:NAS Finder)

airbnb infinite

css scroll

touch device , scroll + event 模擬

SASS

SASS + COMPASS

SASS

Compass

sass framework 

@mixin

@mixin

@mixin

@include

image && sprites

 

structure

  • _colors.scss                             # shared colors
  • _layout.scss                            # template 
  • _main.scss                              # import all
  • _mixins.scss                           # define macro
  • _partials.scss                         # component
  • _typography.scss                  # font
  • pages/                     
    • index
    • item
  • partials/
    • select
    • dialog
  • sites
    • abc123 

colors.scss

.red {
    color:red;
}

.blue {
    color:blue;
}


.bg-red {

}

.bg-blue {

}

page index.scss

#index {

    h1 {
        font-size:2em
    }
    .items {
        background: $bg-color;
    }
    ul {
        list-style:none;
        li {
           display:block;
            width:100%;
            height3em;
            line-height:3em;
        }
    }
}

main.scss

/ Import Plugins
@import "compass/reset";
@import "compass/css3";
@import "compass/utilities";

@import "mixins";
@import "colors";
@import "typography";
@import "partials";
@import "layout";
@import "partials/dialog";
@import "pages/index";

site abc123.scss

$logo: "/images/abc123.png";
$bg-color: #112233;
@import "main";

compass

@include transition-property(transform);
@include transition-duration(.2s);
@include transition-timing-function(ease-in-out);
@include transform (translate(-170px));
=>
  -moz-transition-property: -moz-transform;
  -o-transition-property: -o-transform;
  -webkit-transition-property: -webkit-transform;
  transition-property: transform;
  -moz-transition-duration: .2s;
  -o-transition-duration: .2s;
  -webkit-transition-duration: .2s;
  transition-duration: .2s;
  -moz-transition-timing-function: ease-in-out;
  -o-transition-timing-function: ease-in-out;
  -webkit-transition-timing-function: ease-in-out;
  transition-timing-function: ease-in-out;
  -webkit-transform: translate(170px);
  -moz-transform: translate(170px);
  -ms-transform: translate(170px);
  -o-transform: translate(170px);
  transform: translate(170px);


@include absolute(top .6em right 1em)
=>
position: absolute;
top: .6em;
right: 1em;

compass - image

  .logo {
    $h: image-height($logo);
    $w: image-width($logo);
    height: $h/$w * 160px;
    width: 160px;
    .mylogo {
      background: url($logo);
      background-size: 100% 100%;
      width:100%;
      height:100%;
    }
  }
=>
.logo {
    # $h: 100;
    # $w: 200;
    height: 80px;
    width: 160px;
    .mylogo {
      background: url("images/abc123.png");
      background-size: 100% 100%;
      width:100%;
      height:100%;
    }
  }

media query mixin

@include min-width(360px) {
 span {
   padding:0.5em 1em 0 .5em;  
 }
}
+
@mixin min-width($size) {
   @media screen and (min-width: $size) {
      @content;
   }
}
=>
@media screen and (min-width: 360px) {
  span {
     padding:0.5em 1em 0 .5em;  
  }
}

flex box

@include display-flex;
@include flex-direction(row);
@include align-items(center);
@include justify-content(center);

gulp task

$ = require('gulp-load-plugins')();
gulp.task('compass', function() {
    return gulp.src('scss/sites/*.scss')
        .pipe($.compass({                   # compile scss
            image: './',
            sass: 'scss'
        }))
        .pipe($.combineMediaQueries())      # 合併 media query
        .pipe($.csso())                     # 最佳化
        .pipe(gulp.dest('build'));
});

gulp.task('watch', ['compass'], function () {
    gulp.watch('scss/**/*.scss', ['compass']);
});

Angularjs

ng-touch

[ng-click, ng-swipe]

ng-touch 

  • 觸碰裝置會延遲 300ms 觸發 click
    • 300ms 用來等待 double tap(zoom)

 

  • 透過 touchstart - touchend(trigger click)

 

  • 只處理 ng-click

fastclick

https://github.com/ftlabs/fastclick
 

FastClick is a simple, easy-to-use library for eliminating the 300ms delay between a physical tap and the firing of a click event on mobile browsers. The aim is to make your application feel less laggy and more responsive while avoiding any interference with your current logic.

inner html - fps

innerHTML vs append

https://jsperf.com/appendchild-vs-documentfragment-vs-innerhtml/24

http://ejohn.org/blog/dom-documentfragments/

https://jsperf.com/innerhtml-vs-createelement-test/6

 

實測結果?怪怪的。重複驗證

iphone safari:append > innerhtml

android chrome:append ~= innerhtml

PC chrome:innerhtml > append

Conclusion

mobile

mobile

xlist = xscroll + infinite

ng-touch menu

xscroll menu

tablet

fixed navigation bar

Scroll event 在手

浮動選單 

  • 往下滑隱藏
  • 滑上滑顯示
  • 滑行中停止不處理

fixed navigation bar

Event

  • touch{start,move,end}
  • pan
  • paned
    • velocity
    • deltaY
  • scroll
    • offset
  • scrollend
    • directionY

結論

  • 注意所有小細節(延遲、異狀)

  • 工具(profiling、jsperf)

  • 釐清問題、搞懂原理

  • 最精簡的方式解決問題

mobile web implementation

By mlwmlw

mobile web implementation

  • 152