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 模擬
-
https://github.com/cubiq/iscroll - 2012
-
translate
-
-
http://scrollerjs.com/ - 2014
-
translate3d - gpu
-
-
https://github.com/zynga/scroller - game
-
zoom、pan..
-
SASS
SASS + COMPASS
SASS
CSS Pre compiler
SASS vs SCSS
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