[html]咦🤔, H5还有这些操作呢

3,036 阅读22分钟

本文分类整理了一些H5 API, 可减少前端同学们的调(jia)研(ban)时间

Devices and Sensors 设备和传感器相关

官方文档: www.w3.org/das/

Vibration 震动

官方文档: www.w3.org/TR/vibratio…

参考文档: www.sitepoint.com/the-buzz-ab…

应用场景

  • 增强用户交互体验, 如游戏, 提醒

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

亲测微信小程序webview支持

demo, 强烈建议戳进去感受一下, 如果在移动端浏览, 你会被震到哦

www.audero.it/demo/vibrat…

window.navigator.vibrate(1000)
window.navigator.vibrate([1000, 1000, 2000, 1000, 3000])
// 取消震动
window.navigator.vibrate(0)
window.navigator.vibrate([])
window.navigator.vibrate([0])

Battery Status 电池状态

官方文档: www.w3.org/TR/battery-…

应用场景

  • 根据电池状态做相应节能处理, 改善用户体验, 延长电池寿命
  • 在电池耗尽之前保存关键数据, 防止数据丢失

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

亲测微信小程序webview支持

demo

<!DOCTYPE html>
<html>
<head>
  <title>Battery Status API Example</title>
  <script>
    window.onload = function () {
      function updateBatteryStatus(battery) {
        document.querySelector('#charging').textContent = battery.charging ? 'charging' : 'not charging';
        document.querySelector('#level').textContent = battery.level;
        document.querySelector('#dischargingTime').textContent = battery.dischargingTime / 60;
      }

      navigator.getBattery().then(function(battery) {
        // Update the battery status initially when the promise resolves ...
        updateBatteryStatus(battery);

        // .. and for any subsequent updates.
        battery.onchargingchange = function () {
          updateBatteryStatus(battery);
        };

        battery.onlevelchange = function () {
          updateBatteryStatus(battery);
        };

        battery.ondischargingtimechange = function () {
          updateBatteryStatus(battery);
        };
      });
    };
  </script>
</head>
<body>
  <div id="charging">(charging state unknown)</div>
  <div id="level">(battery level unknown)</div>
  <div id="dischargingTime">(discharging time unknown)</div>
</body>
</html>

Pointer Lock 鼠标锁定

官方文档: w3c.github.io/pointerlock…

应用场景

  • 地图, 游戏, 全景视频中, 让用户不断地移动鼠标来持续旋转或操纵一个3D模型
  • 不用担心指针到达浏览器或者屏幕边缘的那一刻停止

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

www.zhangxinxu.com/study/20170…

var eleImage = document.getElementById('image')
eleImage.requestPointerLock()
document.exitPointerLock()

deviceorientation 设备物理方向 与 devicemotion 设备加速信息

官方文档: www.w3.org/html/ig/zh/…

参考文档: imweb.io/topic/56ab2…

应用场景

  • 摇一摇
  • 体感游戏
  • 罗盘

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

compatibility: developer.mozilla.org/en-US/docs/…

demo

if (window.DeviceMotionEvent) {
    window.addEventListener('devicemotion', shakeEventHandler, false);
} else {
    alert('本设备不支持devicemotion事件');
}

var THRESHOLD = 1000;
var preX = preY = preZ = x = y = z = 0;
var preTime = 0;

function shakeEventHandler(event) {
    var acceleration = event.accelerationIncludingGravity; 
    var curTime = new Date().getTime();
    var diffTime = curTime-preTime;

    if (diffTime > 100) { 
        preTime = curTime;  
        x = acceleration.x;  
        y = acceleration.y;  
        z = acceleration.z;  

        var accelerationDiff = Math.abs(x + y + z - preX - preY - preZ) / diffTime * 10000;  

        if (accelerationDiff > THRESHOLD) {  
            alert("摇一摇有惊喜!");  
        }  
        preX = x;  
        preY = y;  
        preZ = z;  
    }  
}

Ambient Light 环境光

官方文档: www.w3.org/TR/ambient-…

官方文档: developer.mozilla.org/en-US/docs/…

应用场景

  • 阅读时的自适应背景光

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

var sensor = new AmbientLightSensor();
sensor.addEventListener("reading", function (event) {
  console.log(sensor.illuminance)
})

userAgent 用户代理

官方文档: www.html5plus.org/doc/zh_cn/d…

应用场景

  • 简单判断设备类型

demo

//判断当前页面所在的环境是不是微信内置浏览器
function isWeiXin() {
    var ua = window.navigator.userAgent.toLowerCase();
    if (ua.match(/MicroMessenger/i) == 'micromessenger') {
      return true;
    } else {
    return false;
    }
}
//判断苹果、安卓、pc
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
   //判断iPhone|iPad|iPod|iOS  
  window.location.href ="iPhone.html";
} else if (/(Android)/i.test(navigator.userAgent)) { 
  //判断Android  
  window.location.href ="Android.html";
} else { 
  //pc  
  window.location.href ="pc.html";
};

platform 硬件平台

官方文档 developer.mozilla.org/zh-CN/docs/… 返回一个字符串,表示浏览器所在的系统平台类型. 参考文档 developer.mozilla.org/zh-CN/docs/…

demo

document.write("硬件平台: " + navigator.platform);

geolocation 地理位置

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • 需要获取当前设备所在的位置,经纬度 收货地址经常用到

demo

function geoFindMe() {
  var output = document.getElementById("out");

  if (!navigator.geolocation){
    output.innerHTML = "<p>您的浏览器不支持地理位置</p>";
    return;
  }

  function success(position) {
    var latitude  = position.coords.latitude;
    var longitude = position.coords.longitude;

    output.innerHTML = '<p>Latitude is ' + latitude + '° <br>Longitude is ' + longitude + '°</p>';

    var img = new Image();
    img.src = "http://maps.googleapis.com/maps/api/staticmap?center=" + latitude + "," + longitude + "&zoom=13&size=300x300&sensor=false";

    output.appendChild(img);
  };

  function error() {
    output.innerHTML = "无法获取您的位置";
  };

  output.innerHTML = "<p>Locating…</p>";

  navigator.geolocation.getCurrentPosition(success, error);
}

窗口相关

官方文档: www.w3.org/Style/CSS/

Fullscreen 全屏

官方文档: www.w3.org/TR/fullscre… 参考文档: www.sitepoint.com/use-html5-f…

应用场景

  • 全屏展示某元素

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

blogs.sitepointstatic.com/examples/te…

// 让某元素全屏
document.getElementById("myImage").requestFullscreen();
document.addEventListener("fullscreenchange", FShandler);
document.addEventListener("webkitfullscreenchange", FShandler);
document.addEventListener("mozfullscreenchange", FShandler);
document.addEventListener("MSFullscreenChange", FShandler);
// 退出全屏
document.exitFullscreen()
/* 全屏样式 */
:-webkit-full-screen {
}

:-moz-full-screen {
}

:-ms-fullscreen {
}

:fullscreen {
}

print 打印

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • 打印当前窗口的内容

demo

  <html>
    <head>
    <script type="text/javascript">
    function printpage()
      {
      window.print()
      }
    </script>
    </head>
    <body>

    <input type="button" value="Print this page"
    onclick="printpage()" />

    </body>
  </html>

open close 打开新窗口 关闭窗口

官方文档 developer.mozilla.org/zh-CN/docs/…

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • open 是用指定的名称将指定的资源加载到浏览器上下文(窗口 window ,内嵌框架 iframe 或者标签 tab )。如果没有指定名称,则一个新的窗口会被打开并且指定的资源会被加载进这个窗口的浏览器上下文中。
  • close 该方法只能由 window.open 方法打开的窗口的window对象来调用.如果一个窗口不是由脚本打开的,调用该方法时,JavaScript控制台会出现下面的错误: "不能使用脚本关闭一个不是由脚本打开的窗口".

##demo

    let windowObjectReference;
    let strWindowFeatures = `
        menubar=yes,
        location=yes,
        resizable=yes,
        scrollbars=yes,
        status=yes
    `;

    function openRequestedPopup() {
        windowObjectReference = 
        window.open(
            "http://www.cnn.com/", 
            "CNN_WindowName", 
            strWindowFeatures
        );
    }
    // 关闭一个由 window.open()方法打开的窗口
    <script type="text/javascript">
    // 全局变量,存储将要打开的窗口的对象引用.
    var openedWindow;

    function openWindow()
    {
      openedWindow = window.open('moreinfo.htm');
    }
    function closeOpenedWindow()
    {
      openedWindow.close();
    }
    </script>
    // 关闭当前窗口
    <script type="text/javascript">
      function closeCurrentWindow()
      {
        window.close();
      }
    </script>

moveTo moveBy 移动窗口

官方文档 developer.mozilla.org/zh-CN/docs/…

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • 将当前的窗口移动到某一个位置

兼容性

从Firefox 7开始,如果符合下列情况,则普通网页中的JavaScript无法通过调用该函数来移动浏览器窗口

  • 当前窗口或标签页不是由window.open方法创建的
  • 当前标签页所在的窗口包含有多个标签页 区别
  • window moveTo 按照指定的绝对位置移动当前窗口,
  • window.moveBy函数按照与当前位置相对的距离移动当前窗口。

demo

  function origin() {
    // 把窗口移动到坐上角
    window.moveTo(0, 0);
  }

  function budge() {
    moveBy(10, -10);
  }

resize 调整窗口

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • resizeBy 相对于窗口当前大小来调整该窗口的大小
  • resizeTo 以绝对大小方式调整窗口的大小

兼容性

从 Firefox 7 开始,不能改变浏览器窗口的大小了,要依据下面的规则:

  • 不能设置那些不是通过 window.open 创建的窗口或 Tab 的大小。
  • 当一个窗口里面含有一个以上的 Tab 时,无法设置窗口的大小。

demo

    // 缩小窗口
    window.resizeBy(-200, -200);
    // 将窗口设置为整个屏幕的 1/4 大小(面积)
    function quarter() {
      window.resizeTo(
        window.screen.availWidth / 2,
        window.screen.availHeight / 2
      );
    }

scroll 滚动窗口

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • 当文档超过指定区域长度,需要滚动
  • window.scrollBy 相对滚动滚动指定的距离,相对于上次移动的最后位置移动
  • window.scroll 滚动至文档中的绝对位置滚动指定的距离
  • scrollTo()是一步到位,而scrollBy()是逐步累加。

兼容性

developer.mozilla.org/zh-CN/docs/…

demo

    //把纵轴上第100个像素置于窗口顶部
    <button onClick="scroll(0, 100);">点击以向下滚动100像素</button>
    window.scrollTo( 0, 1000 );
    // behavior  类型String,表示滚动行为,支持参数 smooth(平滑滚动),instant(瞬间滚动),默认值auto,实测效果等同于instant
    // 设置滚动行为改为平滑的滚动
    window.scrollTo({ 
        top: 1000, 
        behavior: "smooth" 
    });
    // 向下滚动一页:
    window.scrollBy(0, window.innerHeight);
    // 使用 options:
    window.scrollBy({   
      top: 100,
      left: 100,   
      behavior: "smooth" 
    });

stop 阻止页面资源加载

应用场景

  • 相当于点击了浏览器的停止按钮. 由于已经加载的脚本的顺序, stop() 方法不能阻止已经包含在加载中的文档,但是它能够阻止较大的 图片,新窗口,和一些延迟加载的对象的加载.

兼容性

www.w3cschool.cn/fetch_api/f… stop()方法不建议在Internet Explorer中使用.

demo

    window.stop()

屏幕相关

Screen 屏幕属性

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

获取屏幕当前的一些属性

demo

  // 浏览器窗口在屏幕上的可占用空间上边距离屏幕上边界的像素值。
  var iAvail = window.screen.availTop
  // 返回浏览器可用空间左边距离屏幕(系统桌面)左边界的距离。
  var iAvail = window.screen.availLeft
  // 返回浏览器返回目标设备或缓冲器上的调色板的比特深度。
  document.write("颜色深度: " + screen.colorDepth);
  // 返回屏幕的位深度/色彩深度(bit depth)。根据CSSOM( CSS对象模型 )视图,为兼容起见,该值总为24。
  var iAvail = window.screen.pixelDepth
  // 返回当前屏幕的转向。
  var iAvail = window.Screen.orientation

device​Pixel​Ratio 设备像素比

官方文档 developer.mozilla.org/zh-CN/docs/…

能够返回当前显示设备的物理像素分辨率与 CSS 像素分辨率的比率。此值也可以解释为像素大小的比率:一个 CSS 像素的大小与一个物理像素的大小的比值。简单地说,这告诉浏览器应该使用多少个屏幕的实际像素来绘制单个 CSS 像素。

应用场景

  • 处理标准显示与 HiDPI 或 Retina 显示之间的差异时很有用

兼容性

developer.mozilla.org/zh-CN/docs/…

demo

  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');

  var canvasSize = 200;

  //overriding default window.devicePixelRatio, changing it to 2 on retina display will make canvas clear
  window.devicePixelRatio = 1;

  canvas.width = canvas.height = canvasSize;

  ctx.fillStyle = "#bada55";
  ctx.fillRect(10, 10, 300, 300);
  ctx.fillStyle = "#ffffff";
  ctx.font = '18px Arial';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';

  var x = canvasSize / 2;
  var y = canvasSize / 2;

  var textString = "I love MDN";
  ctx.fillText(textString, x, y);

lockOrientation 锁定屏幕方向

官方文档 developer.mozilla.org/zh-CN/docs/…

官方文档 www.w3.org/TR/screen-o…

应用场景

把屏幕锁定为指定的方向.网站锁定到一个特定的方向,横屏或竖屏,此时,原生应用的格式是可以被指定的。APP只在预设格式下显示—独立于实际的设备方向。通过使用HTML5的 Screen Orientation API, 可以在JavaScript定义屏幕方向。此方法仅适用于已安装的Web apps 或 全屏模式 的Web 页面.

兼容性

IE 11+和Firefox 33+也支持Screen Orientation API,但需要对应的私有前缀

screen.msLockOrientation.lock("portrait-primary"); screen.mozLockOrientation.lock("portrait-primary");

在IE 11+和Firefox 33+中,检测方向变化的事件名也不同,你应该使用带对应前缀的orientationchange,而不是change. 当使用Screen Orientation API时,还需要记住一件事:由于要Fullscreen API一起使用才能起作用,所以不应该使用它来设计网站之类的。对于需要全屏模式的浏览器游戏或其他应用程序,它能有更好的效果。

demo

// 读取当前设备的方向
alert(screen.orientation.type);
alert(screen.orientation.angle);
// 锁定屏幕为竖屏模式,不能设备如何旋转,屏幕都不会切换到横屏模式。
window.screen.lockOrientation([“portrait-primary”,“portrait-secondary”]);
// 锁定屏幕为横屏模式,无能设备如何旋转,屏幕都不会切换到竖屏模式。
window.screen.lockOrientation([“landscape-primary”,“landscape-secondary”]);
// 取消屏幕的锁屏,屏幕回到原始状态,
window.screen.unlockOrientation();

需要注意的点

1.如果你在浏览器中打开了一个新文档,例如,当点击一个链接时,定义的方向将随着全屏模式同时结束。Screen Orientation API仅对当前文档有效。 2.角度为0等同于自然方向,大部分智能手机的自然方向是portrait-primary;90°等同于landscape-primary;180°等同portrait-secondary;270°等同landscape-secondary。不同的设备,angle代表不同的关键字。

Web Performance 性能相关

官方文档: www.w3.org/webperf/ git仓库地址: github.com/w3c/web-per…

Page Visibility Level 2 页面可见性

官方文档: www.w3.org/TR/page-vis…

参考文档: www.sitepoint.com/introductio…

应用场景

  • 页面切到后台时的一些处理, 如暂停音视频, 暂停刷新画布, 减慢甚至停止CPU, 带宽消耗等

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange; 
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
  hidden = "hidden";
  visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
  hidden = "msHidden";
  visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
  hidden = "webkitHidden";
  visibilityChange = "webkitvisibilitychange";
}

// Warn if the browser doesn't support addEventListener or the Page Visibility API
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
  console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
  // 此处可以根据 setInterval 和 requestAnimationFrame 切到后台时的不同表现来hack
} else {
  // Handle page visibility change   
  document.addEventListener(visibilityChange, handleVisibilityChange, false);
}

High Resolution Time Level 2 微秒级精度的时间

官方文档: www.w3.org/TR/hr-time/ 参考文档: blogs.msdn.microsoft.com/ie_cn/2012/…

应用场景

  • 同步动画和音视频, 用户计时, 监测页面性能时有更高的精度
  • 后续调用时间只差不会为负数或0, 单调递增, Date.now()无法保证这一点
  • 起点为文档导航启动的时间, 不受系统时间影响, 更好的做计时任务
  • 嵌套iframe时, 可以统一参考根文档导航启动的时间

兼容性

compatibility: developer.mozilla.org/en-US/docs/… 支持此API的浏览器是IE10,Opera 15, Safari iOS 9和Firefox 15+,不带前缀。Chrome 20+ 需“webkit”前缀,24+不需要前缀。

demo

performance.now()
// 根文档导航启动的时间
// top === window // true
top.performance.now()

User Timing Level 2 用户时序

官方文档: www.w3.org/TR/user-tim… 参考文档: www.sitepoint.com/discovering…

应用场景

  • 测试代码性能, 标记时间戳和测量两个标记之间经过的时间, 无需声明变量和产生额外的性能开销

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

performance.mark("startFoo");
// A time consuming function
foo();
performance.mark("endFoo");

performance.measure("durationFoo", "startFoo", "endFoo");

// Delete all Marks
performance.clearMarks();
// Delete the Measure "durationFoo"
performance.clearMeasure("durationFoo");

Navigation Timing Level 2 导航时序

官方文档: w3c.github.io/navigation-…

参考文档: www.sitepoint.com/profiling-p…

应用场景

  • 获取DNS查找, TCP建立连接, 页面重定向, 构建DOM等消耗的时间
    alt

兼容性

compatibility: caniuse.com/#feat=nav-t…

demo

window.addEventListener('load', function() {
  // 确保加载事件结束
  setTimeout(function () {
    var timing = window.performance.timing
    // 用户经历的总页面加载时间
    var userTime = timing.loadEventEnd - timing.navigationStart
    // DNS查找时间
    var dns = timing.domainLookupEnd - timing.domainLookupStart
    // 连接到服务器花费的时间
    var connection = timing.connectEnd - timing.connectStart
    // 请求发送到服务器并接受响应花费的时间
    var requestTime = timing.responseEnd - timing.requestStart
    // 文档获取(包括访问缓存)的时间
    var fetchTime = timing.responseEnd - timing.fetchStart
  }, 0)
}, false)

// or in console
// Get the first entry
const [entry] = performance.getEntriesByType('navigation')
// Show it in a nice table in the developer console
console.table(entry.toJSON())

Network 网络相关

The Network Information 网络信息

官方文档: www.w3.org/TR/netinfo-… 参考文档: www.sitepoint.com/use-network…

应用场景

  • 评估带宽, 判断网络连接是否受限
  • 根据网络信息响应式的加载高分辨率图片, 不必要的字体, 增加Ajax的timeout参数

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

console.table(navigator.connection)
// downlink: 3.4
// effectiveType: "3g"
// onchange: null
// rtt: 350
// saveData: false

online and offline 在线和离线

应用场景

  • 监测用户在线和离线

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

var condition = navigator.onLine ? "online" : "offline"
window.addEventListener('online',  updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)

信号浮标 Beacon

应用场景

  • 页面卸载完毕前异步发送数据, 不延迟当前页面的卸载以及下一个页面的载入

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

window.addEventListener("unload", logData, false);

function logData() {
  navigator.sendBeacon("/log", analyticsData);
}

Multimedia 多媒体相关

AudioContext 音频上下文

官方文档: www.w3.org/TR/webaudio…

应用场景

  • 解决Audio标签受部分浏览器策略无法自动播放和调整音量的问题
  • 微信浏览器里可以放在wx.ready callbackFn里调用
  • 音频处理, 音频图形化
  • 模拟乐器如钢琴打碟APP, 汤姆猫APP

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

codepen.io/leechikit/e…

// 音頻地址
const SONG1 = 'https://leechikit.github.io/resources/article/AudioContext/song/fingfingxia1.mp3';
// AudioContext对象
let audioContext = null;
// 音频源
let bufferSource = null;
// 音量模块
let gainNode = null;
// 是否播放
let isStart = false;
// 播放按钮元素
let buttonEl = document.querySelector('#button1');
// 音量控件元素
let volumnEl = document.querySelector('#volumn1');

/**
* 创建AudioContext上下文
*
*/
function createAudioContext() {
    try {
        audioContext = new (window.AudioContext || window.webkitAudioContext)();
    } catch (e) {
        alert("Web Audio API is not supported in this browser");
    }
}

/**
* 解码音频文件
*
*/
function decodeAudioData(url, callback) {
    let request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    request.onload = () => {
        audioContext.decodeAudioData(request.response, (buffer) => {
            if (!buffer) {
                alert('error decoding file data: ' + url);
                return;
            } else {
                callback(buffer);
            }
        })
    }
    request.onerror = ()=> {
        alert('BufferLoader: XHR error');
    }
    request.send();
}

/**
* 创建AudioBufferSourceNode
*
*/
function createBufferSource(config) {
    bufferSource = audioContext.createBufferSource();
    bufferSource.buffer = config.buffer;
    bufferSource.loop = config.loop || false;
    bufferSource.onended = () => {
        bufferSource = null;
    }
}

/**
* 创建GainNode对象
*
*/
function createGainNode() {
    gainNode = audioContext.createGain();
}

/**
* 点击播放按钮
*
*/
function buttonClickEvent(buffer) {
    buttonEl.addEventListener('click', (event) => {
        // 停止播放
        if (isStart) {
            event.target.innerText = 'START';
            bufferSource && bufferSource.stop();
            // 开始播放
        } else {
            event.target.innerText = 'STOP';
            createBufferSource({
                buffer,
                loop: true
            });
            createGainNode();
            bufferSource.connect(gainNode);
            gainNode.connect(audioContext.destination);
            bufferSource.start();
        }
        isStart = !isStart;
    });
}

/**
* 改变音量事件
*
*/
function changeVolumnEvent() {
    volumnEl.addEventListener('change', (event) => {
        gainNode && (gainNode.gain.value = event.target.value / 50);
    });
}

/**
* 初始化
*
*/
function init() {
    createAudioContext();
    decodeAudioData(SONG1, (buffer) => {
        buttonEl.setAttribute('data-loaded', true);
        buttonClickEvent(buffer);
        changeVolumnEvent();
    });
}

init();

Media Capture and Streams 媒体捕获和流

官方文档: w3c.github.io/mediacaptur… 官方文档: www.w3.org/2011/04/web… 参考文档: www.sitepoint.com/introductio…

应用场景

  • WebRTC, 实时直播
  • 拍照自定义头像
  • 视频聊天
  • 抖音
  • 美拍

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

www.audero.it/demo/getuse…

var video = document.querySelector('#video')
var myConstraints = {
  video: {
    facingMode: 'user' // 优先调用前置摄像头
  }
}
navigator.mediaDevices.getUserMedia(myConstraints).then((stream) => {
  video.src = window.URL.createObjectURL(stream)
  video.play()
}, (error) => {
  console.error(error.name || error)
})

Web Speech web语音

官方文档: www.w3.org/community/s… 官方文档: w3c.github.io/speech-api/… 参考文档: www.sitepoint.com/talking-web…

应用场景

  • 无障碍阅读
  • 语音控制
  • 游戏分数, 天气, 股市, 新闻播报

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

codepen.io/matt-west/p…

// Create the utterance object
// 语音合成
var utterance = new SpeechSynthesisUtterance();
utterance.text = 'My name is Dino';
utterance.lang = 'it-IT';
utterance.rate = 1.2;
utterance.onend = function() {
  window.speechSynthesis.speak(utterance);
});

offlineaudiocontext 音频处理图

官方文档 www.w3.org/TR/webaudio…

官方文档 developer.mozilla.org/zh-CN/docs/…

与 AudioContext 标准相反的是, OfflineAudioContext 不在硬件设备渲染音频;相反,它尽可能快地生成音频,输出一个 AudioBuffer 作为结果。

demo

  // 定义一个在线或者离线的音频上下文
var audioCtx = new AudioContext();
var offlineCtx = new OfflineAudioContext(2,44100*40,44100);

source = offlineCtx.createBufferSource();

// 使用 XHR 去加载一个音轨,
// 使用 decodeAudioData 去解码,
// 使用 OfflineAudioContext 去渲染它

function getData() {
  request = new XMLHttpRequest();

  request.open('GET', 'viper.ogg', true);

  request.responseType = 'arraybuffer';

  request.onload = function() {
    var audioData = request.response;

    audioCtx.decodeAudioData(audioData, function(buffer) {
      myBuffer = buffer;
      source.buffer = myBuffer;
      source.connect(offlineCtx.destination);
      source.start();
      //source.loop = true;
      offlineCtx.startRendering().then(function(renderedBuffer) {
        console.log('渲染完全成功');
        var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        var song = audioCtx.createBufferSource();
        song.buffer = renderedBuffer;

        song.connect(audioCtx.destination);

        play.onclick = function() {
          song.start();
        }
      }).catch(function(err) {
          console.log('渲染失败: ' + err);
          // 注意: 当 OfflineAudioContext 上 startRendering 被立刻调用,Promise 应该被 reject
      });
    });
  }

  request.send();
}

// 运行 getData 去开始这个进程

getData();

Web Notification 消息提醒

官方文档: www.w3.org/TR/notifica…

参考文档: www.zhangxinxu.com/wordpress/2…

应用场景:

  • 消息推送, 聊天

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

www.zhangxinxu.com/study/20160…

enumerateDevices 获取可用设备

官方文档:developer.mozilla.org/zh-CN/docs/…

应用场景:

  • 获取当前媒体详细信息 请求一个可用的媒体输入和输出设备的列表,例如麦克风,摄像机,耳机设备等。 返回的 Promise 完成时,会带有一个描述设备的 MediaDeviceInfo 的数组。

兼容性

developer.mozilla.org/zh-CN/docs/…

demo

if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
  console.log("不支持 enumerateDevices() .");
  return;
}
// 列出相机和麦克风.
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
  devices.forEach(function(device) {
    console.log(device.kind + ": " + device.label +
                " id = " + device.deviceId);
  });
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

Semantics 语义相关

MATHML 数学标签

官方文档: www.w3.org/Math/ 官方文档: w3c.github.io/mathml/math…

应用场景

  • 数学公式的展示

兼容性

compatibility: developer.mozilla.org/en-US/docs/…

demo

alt

<mrow>
  <mi>x</mi>
  <mo>=</mo>
  <mfrac>
    <mrow>
      <mrow>
        <mo>-</mo>
        <mi>b</mi>
      </mrow>
      <mo>&#xB1;<!--plus-minus sign--></mo>
      <msqrt>
        <mrow>
          <msup>
            <mi>b</mi>
            <mn>2</mn>
          </msup>
          <mo>-</mo>
          <mrow>
            <mn>4</mn>
            <mo>&#x2062;<!--invisible times--></mo>
            <mi>a</mi>
            <mo>&#x2062;<!--invisible times--></mo>
            <mi>c</mi>
          </mrow>
        </mrow>
      </msqrt>
    </mrow>
    <mrow>
      <mn>2</mn>
      <mo>&#x2062;<!--invisible times--></mo>
      <mi>a</mi>
    </mrow>
  </mfrac>
</mrow>

WindowOrWorkerGlobalScope 通信相关

btoa 编码

官方文档 https://developer.mozilla.org/zh-CN/docs/Web/API/WindowBase64/btoa

应用场景

  • 对可能导致通信问题的数据进行编码,然后将其传输,然后再使用该atob()方法对数据进行解码。
  • 从String对象创建一个base-64编码的ASCII字符串,其中字符串中的每个字符都被视为二进制数据的字节。

demo

    let encodedData = window.btoa("Hello, world"); // base64 编码

atob 解码

官方文档 https://developer.mozilla.org/zh-CN/docs/Web/API/WindowBase64/atob

应用场景

解码用btoa编码一个可能在传输过程中出现问题的数据 并且在接受数据之后,使用 atob() 方法再将数据解码。例如:你可以编码、传输和解码操作各种字符,比如0-31的ASCII码值。

兼容性

https://developer.mozilla.org/zh-CN/docs/Web/API/WindowBase64/atob#Specification

demo

  let decodedData = window.atob(encodedData); // 解码

postMessage Window对象之间的跨源通信

官方文档 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

应用场景

  • 在页面和它产生的弹出窗口之间,或者在页面和嵌入其中的iframe之间。 通常,当且仅当它们源自的页面共享相同的协议、端口号和主机(也称为“同源策略”)时,允许不同页面上的脚本相互访问。window.postMessage()提供一种受控制的机制来安全地规避这种限制(如果使用得当)。
  • 从广义上讲,一个窗口可以获得对另一个窗口的引用(例如,可以使用targetWindow=window.opener),然后使用targetWindow.postMessage() 在其上发送一个MessageEvent。然后,接收窗口可根据需要自由处理此事件。传递给window.postMessage()的参数(即“message”)通过事件对象暴露给接收窗口。

兼容性

developer.mozilla.org/zh-CN/docs/…

demo

  /*
  * A窗口的域名是<http://example.com:8080>,以下是A窗口的script标签下的代码:
  */

  var popup = window.open(...popup details...);

  // 如果弹出框没有被阻止且加载完成

  // 这行语句没有发送信息出去,即使假设当前页面没有改变location(因为targetOrigin设置不对)
  popup.postMessage("The user is 'bob' and the password is 'secret'",
                    "https://secure.example.net");

  // 假设当前页面没有改变location,这条语句会成功添加message到发送队列中去(targetOrigin设置对了)
  popup.postMessage("hello there!", "http://example.org");

  function receiveMessage(event)
  {
    // 我们能相信信息的发送者吗?  (也许这个发送者和我们最初打开的不是同一个页面).
    if (event.origin !== "http://example.org")
      return;

    // event.source 是我们通过window.open打开的弹出页面 popup
    // event.data 是 popup发送给当前页面的消息 "hi there yourself!  the secret response is: rheeeeet!"
  }
  window.addEventListener("message", receiveMessage, false);
  /*
  * 弹出页 popup 域名是<http://example.org>,以下是script标签中的代码:
  */

  //当A页面postMessage被调用后,这个function被addEventListenner调用
  function receiveMessage(event)
  {
    // 我们能信任信息来源吗?
    if (event.origin !== "http://example.com:8080")
      return;

    // event.source 就当前弹出页的来源页面
    // event.data 是 "hello there!"

    // 假设你已经验证了所受到信息的origin (任何时候你都应该这样做), 一个很方便的方式就是把enent.source
    // 作为回信的对象,并且把event.origin作为targetOrigin
    event.source.postMessage("hi there yourself!  the secret response " +
                            "is: rheeeeet!",
                            event.origin);
  }

  window.addEventListener("message", receiveMessage, false);

Storage 存储相关

session​Storage 会话存储

官方文档 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/sessionStorage

应用场景

  • 非常适合SPA(单页应用程序) 方便在各业务模块进行传值
  • 用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数

特点

  • 同源策略限制。若想在不同页面之间对同一个sessionStorage进行操作,这些页面必须在同一协议、同一主机名和同一端口下。(IE 8和9存储数据仅基于同一主机名,忽略协议(HTTP和HTTPS)和端口号的要求)

  • 单标签页限制。sessionStorage操作限制在单个标签页中,在此标签页进行同源页面访问都可以共享sessionStorage数据。

  • 只在本地存储。seesionStorage的数据不会跟随HTTP请求一起发送到服务器,只会在本地生效,并在关闭标签页后清除数据。(若使用Chrome的恢复标签页功能,seesionStorage的数据也会恢复)。

  • 存储方式。seesionStorage的存储方式采用key、value的方式。value的值必须为字符串类型(传入非字符串,也会在存储时转换为字符串。true值会转换为"true")。

  • 存储上限限制:不同的浏览器存储的上限也不一样,但大多数浏览器把上限限制在5MB以下。

兼容性

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/sessionStorage#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7

demo

   sessionStorage.setItem('myCat', 'Tom');
   // 获取文本输入框
   let field = document.getElementById("field");
   
   // 检测是否存在 autosave 键值
   // (这个会在页面偶然被刷新的情况下存在)
   if (sessionStorage.getItem("autosave")) {
     // 恢复文本输入框的内容
     field.value = sessionStorage.getItem("autosave");
   }
   
   // 监听文本输入框的 change 事件
   field.addEventListener("change", function() {
     // 保存结果到 sessionStorage 对象中
     sessionStorage.setItem("autosave", field.value);
   });
   // 也可以存储json对象
   var userEntity = {
       name: 'tom',
       age: 22
   };
   
   // 存储值:将对象转换为Json字符串
   sessionStorage.setItem('user', JSON.stringify(userEntity));
   
   // 取值时:把获取到的Json字符串转换回对象
   var userJsonStr = sessionStorage.getItem('user');
   userEntity = JSON.parse(userJsonStr);
   console.log(userEntity.name); // => tom

localStorage 本地存储

官方文档 developer.mozilla.org/zh-CN/docs/…

应用场景

  • 数据比较大的临时保存方案。如在线编辑文章时的自动保存。

  • 多页面访问共同数据。sessionStorage只适用于同一个标签页,localStorage相比而言可以在多个标签页中共享数据。

特点

  • 同源策略限制。若想在不同页面之间对同一个localStorage进行操作,这些页面必须在同一协议、同一主机名和同一端口下。(IE8和9存储数据仅基于同一主机名,忽略协议(HTTP和HTTPS)和端口号的要求)

  • 只在本地存储。localStorage的数据不会跟随HTTP请求一起发送到服务器,只会在本地生效。

  • 永久保存。保存的数据没有过期时间,直到手动去除。

  • 存储方式。localStorage的存储方式采用key、value的方式。value的值必须为字符串类型(传入非字符串,也会在存储时转换为字符串。true值会转换为"true")。

  • 存储上限限制:不同的浏览器存储的上限也不一样,但大多数浏览器把上限限制在5MB以下。

  • 同浏览器共享。localStorage的数据可以在同一个浏览器的不同标签页的同源页面之间共享。

兼容性

developer.mozilla.org/zh-CN/docs/…

Input 输入相关

Clipboard (Cut & Copy & Paste) 剪贴板

官方文档 developer.mozilla.org/zh-CN/docs/…

developer.mozilla.org/en-US/docs/…

developer.mozilla.org/en-US/docs/…

应用场景

  • 复制粘贴

兼容性

developer.mozilla.org/en-US/docs/…

developer.mozilla.org/en-US/docs/…

developer.mozilla.org/en-US/docs/…

demo

var logTarget = document.getElementById('logTarget');
function useAsyncApi() {
  return document.querySelector('input[value=async]').checked;
}
function log(event) {
  var timeBadge = new Date().toTimeString().split(' ')[0];
  var newInfo = document.createElement('p');
  newInfo.innerHTML = '<span class="badge">' + timeBadge + '</span> ' + event + '</b>.';
  logTarget.appendChild(newInfo);
}

function performCopyEmail() {
  var selection = window.getSelection();
  var emailLink = document.querySelector('.js-emaillink');

  if (useAsyncApi()) {
    navigator.clipboard.writeText(emailLink.textContent)
      .then(() => log('Async writeText successful, "' + emailLink.textContent + '" written'))
      .catch(err => log('Async writeText failed with error: "' + err + '"'));
  } else {
    selection.removeAllRanges();
    var range = document.createRange();
    range.selectNode(emailLink);
    selection.addRange(range);
  
    try {
      var successful = document.execCommand('copy');
      var msg = successful ? 'successful' : 'unsuccessful';
      log('Copy email command was ' + msg);
    } catch (err) {
      log('execCommand Error', err);
    }
    
    selection.removeAllRanges();
  }
}

function performCutTextarea() {
  var cutTextarea = document.querySelector('.js-cuttextarea');
  if (useAsyncApi()) {
    navigator.clipboard.writeText(cutTextarea.textContent)
      .then(() => {
        log('Async writeText successful, "' + cutTextarea.textContent + '" written');
        cutTextarea.textContent = '';
      })
      .catch(err => log('Async writeText failed with error: "' + err + '"'));
  } else {
    var hasSelection = document.queryCommandEnabled('cut');
    cutTextarea.select();

    try {
      var successful = document.execCommand('cut');
      var msg = successful ? 'successful' : 'unsuccessful';
      log('Cutting text command was ' + msg);
    } catch (err) {
      log('execCommand Error', err);
    }
  }
}

// Get the buttons
var cutTextareaBtn = document.querySelector('.js-textareacutbtn');
var copyEmailBtn = document.querySelector('.js-emailcopybtn');

// Add click event listeners
copyEmailBtn.addEventListener('click', performCopyEmail);
cutTextareaBtn.addEventListener('click', performCutTextarea);

function logUserOperation(event) {
  log('User performed <b>' + event.type + '</b> operation. Payload is: <b>' + event.clipboardData.getData('text/plain') + '</b>');
}

document.addEventListener('cut', logUserOperation);
document.addEventListener('copy', logUserOperation);
document.addEventListener('paste', logUserOperation);

touch onpointerdown 触摸手势

官方文档 developer.mozilla.org/zh-CN/docs/…

developer.mozilla.org/zh-CN/docs/…

应用场景

  • 拖拽功能
  • 手机触摸事件

兼容性

developer.mozilla.org/zh-CN/docs/…

developer.mozilla.org/zh-CN/docs/…

demo

window.onload = function startup() {
  var el = document.getElementsByTagName("canvas")[0];
  el.addEventListener("touchstart", handleStart, false);
  el.addEventListener("touchend", handleEnd, false);
  el.addEventListener("touchmove", handleMove, false);
  log("初始化成功。")
}
<html>
  <script>
  function downHandler(ev) {
  // Process the pointerdown event
  }
  function init() {
  var el=document.getElementById("target1");
  el.onpointerdown = downHandler;
  }
  </script>
  <body onload="init();">
  <div id="target1"> Touch me ... </div>
  <div id="target2" onpointerdown="downHandler(event)"> Touch me ... </div>
  </body>
</html>

refer 参考