@ChingHanHo

I Build Stuff.

Facebook Instant Articles「即時文章」是什麼?

速度

行動裝置時代瓶頸:

  • 手機頻寬小;
  • 手機速度慢;

但是人們希望:

  • 速度快;
  • 速度要快;
  • 速度更快;

快有什麼好處?遠古的網路傳說:

  • Amazon 網頁平均載入時間多 1 秒,公司年度營收少 16 億美元;
  • Google 網頁平均載入時間多 0.4 秒,每天搜尋次數減少 800 萬;
  • 使用者開啟網頁 4 秒內沒有出現任何內容便會放棄;

所以 Facebook 推出「即時文章」,讓文章內容可以在毫秒之間顯示。

SCSS 物件導向模組設計 (1)

三年前曾經寫過「劣以為的 OOCSS 和 SMACSS 以及其他 CSS 規範」探討 OOCSS 模組化的方法論,時至今日對於模組化設計又有新的認識跟理解,大原則跟三年前的方法沒有出入,只是多做解釋跟補充。

OOCSS 物件導向是解釋設計原則,但是不限於語法的設計。

如果這個議題有興趣,歡迎繼續往下閱讀,如果有任何想法也歡迎留言與我討論!

使用一個 HTML 樣版引擎的選擇重點

語法

首先當然是要喜歡上該樣版引擎的語法,因為使用樣版引擎的主要目的就是為了加速撰寫 HTML 的生產力,給先讓自己喜歡使用它,才有辦法寫得有效率。多數樣版引擎的入口頁會用簡單的範例,快速火力展示它的特點,這是很好的開始。但也因為這是精心設計的著陸頁,目的是攻取心裡的小惡魔,所以在選擇採用這套樣版引擎前也得特別小心。

擴充性

一個好的樣版引擎可以讓自己掌控專案的伸縮性,例如註冊新的 helper 跟 block,節省撰寫重複的程式碼,靈活地設計版型架構。

安全性

對於經驗不足的開發者來說這很容易鑄成大錯,在沒有意識下的輸出未消毒的內容,都可能會造成使用者傷害,而一個好的樣版引擎應該要預設消毒輸出。如果對自己的經驗很有信心,覺得這是初學者才會犯的錯誤,但也不能夠保證其他同事們不會粗心大意。

勿矯枉過正

使用樣版引擎是為了增加團隊在撰寫 HTML 的效率,所以應該以團隊的技術水平作為優先考量,如果團隊的平均技術水平沒有達到而貿然採用也只是增加大家困擾而已。 不要為了使用而使用。

使用 Zepto + Velocity 無縫取代 jQuery 更輕巧

zeptojs

Zepto 是個跟 jQuery API 相容的套件,但是非常輕巧。

jQuery 1.11.2 不壓縮 278KB,壓縮後是 94.8KB。儘管 jQuery 2.0 比 jQuery 1.11 減少了 12% 的體積大小,仍然是個 200KB 級的套件。而 Zepto 不壓縮 56KB,壓縮後大約是 24.5KB,比 jQuery 平均小了 74%!

Zepto 極其輕巧的秘訣在於它預設只有 jQuery 最關鍵的幾個核心功能,並且用友善的模組化設計,保持每個功能能夠輕易地被擴充。

9 個存取硬體裝置的 Javascript API

原生 HTML5 和 Javascript API 可以直接從瀏覽器存取硬體組件和感測器。這裏的硬體裝置主要是指手機。

點擊連結傳送簡訊

1
2
3
4
5
6
<a href="tel:0912345678">打給我!</a>

<!-- Android -->
<a href="sms:0912345678?body=你到哪了?">傳簡訊給我!</a>
<!-- iOS -->
<a href="sms:0912345678&amp;body=你到哪了?">傳簡訊給我!</a>

延伸資料:

地理定位 API

1
2
3
4
5
6
if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(function (position) {
    var whereareyou = position.coords.latitude + ' ,' + position.coords.longitude
    alert(whereareyou)
  })
}

裝置方向與裝置體感 API

這兩個功能是建立在裝置的陀螺儀和指南針感測器上,它能夠傳回目前裝置的旋轉角度,以及三個維度。

1
2
3
4
5
6
7
8
9
if (window.DeviceOrientationEvent) {
  window.addEventListener('deviceorientation', function(event) {
    // gamma 是左到右傾斜的角度
    // beta  是前到後傾斜的角度
    // alpha 是裝置面向在指南針方位上的角度
    document.body.innerHTML = event.gamma + ' ,' + event.beta + ' ,' + event.alpha

  }, false)
}

有了裝置體感的 API,也可以做出搖一搖復原輸入的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (window.DeviceMotionEvent) {
  window.addEventListener('devicemotion', function(evnet) {

    document.body.innerHTML = evnet.acceleration.x + '<br/>' + evnet.acceleration.y + '<br/>' + evnet.acceleration.z

    // 加速感測
    console.log(evnet.acceleration.x)
    console.log(evnet.acceleration.y)
    console.log(evnet.acceleration.z)

    // 加速感測包括重力參數
    console.log(evnet.accelerationIncludingGravity.x)
    console.log(evnet.accelerationIncludingGravity.y)
    console.log(evnet.accelerationIncludingGravity.z)

    // 旋轉率
    console.log(evnet.rotationRate.alpha)
    console.log(evnet.rotationRate.beta)
    console.log(evnet.rotationRate.gamma)
  }, false)
}

延伸資料:

震動馬達

目前只支援 Android 的 Chrome 以及 Opera、Firefox,iOS 尚不支援。

1
2
3
4
5
var btn = document.getElementById('btn')
var vibrate = navigator.vibrate || navigator.mozVibrate || navigator.webkitVibrate
btn.addEventListener('click', function (event) {
  vibrate(1000)
})

延伸資料:

剩餘電力管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery

function log(_battery) {
  document.body.innerHTML = '目前電力剩下:' + (_battery.level * 100) + '%'
  _battery.addEventListener('chargingchange', function() {
    alert('開始充電!')
  }, false)
}

if (navigator.getBattery) {
  navigator.getBattery().then(log)
} else if (battery) {
  log(battery)
}

亮度感測器

目前只有 Firefox 支援這個 API。

1
2
3
4
5
6
if ('ondevicelight' in window) {
  window.addEventListener("devicelight", function (event) {
  // 回傳的是亮度單位 lux
  console.log(event.value + " lux")
  })
}

近距離感測 API

這個也是只有 Firefox 支援。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if('ondeviceproximity' in window) {
  // Fired when object is in the detection zone
  window.addEventListener('deviceproximity', function (event) {
      // Object distance in centimeters
      console.log(event.value + " centimeters")
    })
} else {
  console.log("deviceproximity not supported")
}

if('ondeviceproximity' in window){
  // Fired when object is in the detection zone
  window.addEventListener('userproximity', function (event) {
    if(event.near == true) {
      console.log("Object is near")
    } else {
      console.log("Object is far")
    }
  })
} else {
  console.log("userproximity not supported")
}

參考: