尤睿, ryou@mozilla.com
h
, j
, k
, l
, 0
, $
, Space
, Shift+Space
, PageDown
, PageUp
, Home
, End
, Esc
The Web is the platform.
More Web APIs are coming ...
更好的用户体验,更流畅的人机交互
检测页面可见性
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
myVideo.pause();
} else {
myVideo.play();
}
}, false);
requestAnimationFrame
会自动停止。Audio 和 Video 不会。全屏显示页面或某个元素
// detect whether Fullscreen mode is supported
if (document.mozFullScreenEnabled) {
// Fullscreen on whole document
document.body.mozRequestFullScreen();
// Fullscreen on one element
document.getElementById('fullscreen-code').mozRequestFullScreen();
}
moz
前缀,需要获取用户同意。document.fullScreenElement
来检测全屏状态,获取全屏元素。:fullscreen
, :-moz-full-screen
) 来设置针对全屏模式的样式。追踪用户的位置和运动
navigator.geolocation.getCurrentPosition(function(position) {
var coords = position.coords;
// decimal degrees
console.log(coords.latitude + ", " + coords.longitude);
console.log(coords.altitude + "meters");
}, function(error) {
if (error.code == 1) {
console.log("Permission denied");
} else {
console.log(error.code);
}
}, {maximumAge: 500});
watchPosition
和 clearWatch
来 开启 / 关闭 追踪。音乐,摄影,摄像,电影,动漫,游戏……
2D 像素级绘制,硬件加速支持
var canvas = document.getElementById('rect');
var context = canvas.getContext('2d');
context.fillStyle = 'rgb(200,0,0)';
context.fillRect (10, 10, 300, 300);
context.fillStyle = 'rgba(0, 0, 200, 0.5)';
context.fillRect (140, 140, 300, 300);
OpenGL 的 Web 版本, canvas 的 3D 绘制环境
加载、播放、合成音频数据
// Load dynamically
var audio = new Audio();
audio.src = '../demos/visibility/johann_sebastian_bach_air.ogg';
audio.addEventListener('MozAudioAvailable', function(event) {
console.log(event.time + "s");
}, false);
audio.play();
MP3
。录制、处理音频流和视频流
var video = document.getElementById('my-video');
navigator.getUserMedia({'video': true}, function(mediaStream) {
video.src = URL.createObjectURL(mediaStream);
video.play();
}, function(error) {
console.error('Video capture error: ', error.code);
});
// Capture
var ctx = myCanvas.getContext('2d');
ctx.drawImage(video, 0, 0);
在预定义的目录中读写图片、音乐、视频等
var name = "my-cat-with-80s-camera-filter.png",
storage = navigator.getDeviceStorage("pictures"),
request = storage.addNamed(myImageBlob, name);
request.onsuccess = function() {
console.log('%d saved', this.result.name);
// storage.delete(name)
};
request.onerror = function() {
console.log('Could not save picture, #' + this.result.code);
};
越来越接近原生应用
在后台独立运行任务
// my_task.js will run in its background threads
var worker = new Worker('my_task.js');
worker.addEventListener('message', function(event) {
console.log('Worker send a message back: ' + event.data);
}, false);
// Start the worker.
worker.postMessage(JSON.stringify(myWorkerData));
高效操作二进制数据
// a buffer with 16 bytes
var buffer = new ArrayBuffer(16);
// a view treating the data as 32-bit signed integers
var int32View = new Int32Array(buffer);
// Access the fields in the array just like a normal array
for (var i=0; i < int32View.length; i++) {
int32View[i] = i*2;
console.log(int32View[i]);
}
Array
慢。与 Web Workers
进行数据交换的高效方式
worker.postMessage = worker.webkitPostMessage || worker.postMessage;
var bigData = new ArrayBuffer(1);
// // New argument: postMessage(message, targetOrigin, transferables);
worker.postMessage({other: 'data', data: bigData}, [bigData]);
if (bigData.byteLength) {
console.error('Transferables are not supported in your browser!');
} else {
// Buffer got reset, transferables are supported.
}
编译模式与静态类型
function DiagModule(stdlib) {
"use asm";
var sqrt = stdlib.Math.sqrt;
function square(x) {
x = +x;
return +(x*x);
}
function diag(x, y) {
x = +x;
y = +y;
return +sqrt(square(x) + square(y));
}
return { diag: diag };
}
var fast = DiagModule(window); // produces AOT-compiled version
console.log(fast.diag(3, 4)); // 5
手机特有功能
拨出、接听电话
// First, obtain a telephony object.
var telephony = navigator.mozTelephony;
// Check if the speaker is enabled or phone is muted.
concole.log(telephony.speakerEnabled, telephony.muted);
// Then, we dial out.
var outgoing = telephony.dial(myPhoneNumber);
// Event handlers for the call.
outgoing.onconnected = function(event) {
/* Do something when the callee picks up the call. */
};
outgoing.ondisconnected = function(event) {
/* Do something when the call finishes. */
};
// Receive an incoming call.
telephony.onincoming = function onincoming(event) {
var incoming = event.call;
if (incoming.number == myBlockedNumber) {
// Hang up
incoming.hangUp();
return;
}
// Answer the call.
incoming.answer();
};
发送、接受短信
var request = navigator.mozSms.send(myNumber, "Hello World!");
request.onsuccess = function() {
var message = request.result;
console.log(
message.delivery, // 'sent' or 'received'
message.read // boolean
);
}
request.onerror = function(error) {
console.error('Could not send message: ' + error);
}
振动设备
// Single vibration
navigator.mozVibrate(200);
// Pattern
navigator.mozVibrate([200, 100, 200, 100, 400]);
// Cancel existing vibrations
navigator.mozVibrate(0);
获取环境情况与设备状态
获取、追踪电池状态和充电水平
var battery = navigator.battery;
console.log('Battery charging: ', battery.charging); // true
console.log('Battery level: ', battery.level); // 0.58
console.log('Battery discharging time: ', battery.dischargingTime);
// Listen to change events
battery.addEventListener('chargingchange', function(e) {
console.warn('Battery charge change: ', battery.charging);
}, false);
获取、改变屏幕方向
console.log(window.screen.mozOrientation);
if (window.screen.mozLockOrientation('landscape-primary')) {
console.log('orientation was locked');
} else {
console.log('lock failed');
}
manifest.webapp
中使用orientation
属性锁定方向。访问加速传感器、陀螺仪与指南针
window.addEventListener('deviceorientation',function(event){
// left-to-right tilt in degrees, where right is positive
var tiltLR = event.gamma;
// front-to-back tilt in degrees, where front is positive
var tiltFB = event.beta;
// compass direction the device is facing in degrees
var dir = event.alpha
// call our orientation event handler
rotateMyStuff(tiltLR, tiltFB, dir);
}, false);
检测设备屏幕是否被覆盖
window.addEventListener('userproximity', function(event) {
console.log(event.near ? 'Hello' : 'Come closer!');
}, true);
检测设备附近的光线强度。
window.addEventListener('devicelight', function(event) {
console.log('SI lux', event.value);
}, true);