2w+字长文:2024年 PWA 不温不火,盘点 40+逆天特性

最近读到一篇关于PWA的文章《WHATWEBCANDOTODAY?》,加上本身自己对PWA这个专题也比较感兴趣,所以抽空梳理了PWA目前主流功能以及功能描述。

文章从用户体验、Native行为拉齐、App生命周期、PWA周边功能、CameraMicrophone、设备特征、操作系统、用户Input输入、屏幕和输出等众多维度描述了PWA特征。

1.PWA与无缝体验离线模式

Web应用程序可以使用两种技术提供离线体验,较旧的实现,即应用程序缓存(ApplicationCache)已在浏览器中广泛实现,但由于各种概念和设计缺陷,现在正在弃用。

现代替代方案称为CacheAPI,可在ServiceWorker中使用,在HTTPS上运行的Web应用程序可以请求浏览器安装的独立代码单元。然后,该单元与所属的Web应用程序分开运行,并通过事件与其进行通信。ServiceWorker是渐进式Web应用程序(PWA)理念的基本构建,除了作为推送通知(PushNotifications)、后台同步(BackgroundSync)或地理围栏(Geofencing)等多个复杂API的推动者之外,还可以用作功能齐全的Web代理。其可以拦截所有HTTP请求,改变其内容或行为甚至管理离线缓存。

(path)()()
BackgroundSyncAPI

BackgroundSyncAPI允许授权的Web应用程序不依赖于稳定的互联网连接,并将Web相关操作推迟到网络连接可用时。API绑定到ServiceWorker,它是与所属Web应用程序分离的代码执行模型,允许后台同步在应用程序窗口关闭后也可以运行。

BackgroundSyncAPI本身只是向应用程序发出有关已恢复连接的信号的一种方式。它可以与任何离线存储解决方案一起使用,以实现数据同步方案或应用程序离线时发出的网络请求的重放机制。

('syncTag')('sync',listener)
PaymentRequestAPI

PaymentRequestAPI允许Web应用程序将付款结帐流程委托给操作系统,从而允许其使用平台本机可用并为用户配置的任何方法和付款提供商。这种方法消除了应用程序端处理复杂结账流程的负担,缩小了支付提供商集成的范围,并确保用户更好地熟悉。

constrequest=newPaymentRequest(buildSupportedPaymentMethodData(),buildShoppingCartDetails(),);functionbuildSupportedPaymentMethodData(){return[{supportedMethods:""}];}functionbuildShoppingCartDetails(){return{id:"order-123",displayItems:[{label:"Exampleitem",amount:{currency:"USD",value:"1.00"},},],total:{label:"Total",amount:{currency:"USD",value:"1.00"},},};}
CredentialManagementAPI

CredentialManagementAPI允许授权的Web应用程序代表用户以编程方式存储和请求用户凭证(例如:登录名和密码或联合登录数据)。该API提供了浏览器内置或第三方密码存储的替代方案,允许Web应用程序检测何时以及如何存储和读取凭证,例如:提供自动登录功能。

functionstoreCredential(){();if(!){alert('CredentialManagementAPInotsupported');return;}letcredentialForm=('credential-form');letcredential=newPasswordCredential(credentialForm);//创建证书(credential).then(()=log('Storingcredentialfor'++'(resultcannotbecheckedbythewebsite).')).catch((err)=log('Errorstoringcredentials:'+err));}functionrequestCredential(){if(!){alert('CredentialManagementAPInotsupported');return;}letmediationValue=('credential-form').;({password:true,mediation:mediationValue}).then(credential={letresult='none';if(credential){result=+','+(/./g,'*');}log('Credentialread:'+result+'');}).catch((err)=log('Errorreadingcredentials:'+err));}functionpreventSilentAccess(){if(!){alert('CredentialManagementAPInotsupported');return;}().then(()=log('Silentaccessprevented(()call).')).catch((err)=log('Errorpreventingsilentaccess:'+err));}functionwaitForSms(){if('OTPCredential'inwindow){log(':\n\n'+'Yourverificationcodeis:123ABC\n\n'+'@","background_color":"5.letdecoder=newTextDecoder();('target').innerHTML='Received:'+();}catch(error){('target').innerHTML=error;}}
WebSerialAPI

WebSerialAPI允许Web应用程序与通过串行端口(SerialPort)连接到系统的设备进行交互。为了授权应用程序访问设备,用户需要在浏览器的UI中确认意图,而该意图只能通过手势启动(例如,单击按钮,但不能通过任意JavaScript自动启动)。API通过一对流公开连接,一个用于读取,一个用于写入SerialPort。

('connectButton').addEventListener('click',()={if(){connectSerial();}else{alert('WebSerialAPInotsupported.');}});asyncfunctionconnectSerial(){constlog=('target');try{constport=();({baudRate:9600});constdecoder=newTextDecoderStream();();constinputStream=;constreader=();while(true){const{value,done}=();if(value){+=value+'\n';}if(done){('[readLoop]DONE',done);();break;}}}catch(error){=error;}}
5.PWA与CameraMicrophoneAudioVideoCapture
functiongetUserMedia(constraints){if(){(constraints);}varlegacyApi=||||||;if(legacyApi){returnnewPromise(function(resolve,reject){(navigator)(constraints,resolve,reject);});}}functiongetStream(type){if(!!!!!){alert('UserMediaAPInotsupported.');return;}varconstraints={};constraints[type]=true;getUserMedia(constraints).then(function(stream){varmediaControl=(type);if('srcObject'inmediaControl){=stream;}elseif(){=stream;}else{=(||).createObjectURL(stream);}();}).catch(function(err){alert('Error:'+err);});}
AdvancedCameraControls

ImageCaptureAPI允许Web应用程序控制设备相机的高级设置,例如:变焦、白平衡、ISO或焦点,并根据这些设置拍照,其依赖于可能从流中获取的streamVideoTrack对象。

functiongetUserMedia(options,successCallback,failureCallback){varapi=||||||;if(api){(navigator)(options,successCallback,failureCallback);}}vartheStream;functiongetStream(){if(!!!!){alert('UserMediaAPInotsupported.');return;}varconstraints={video:true};getUserMedia(constraints,function(stream){varmediaControl=('video');if('srcObject'inmediaControl){=stream;}elseif(){=stream;}else{=(||).createObjectURL(stream);}theStream=stream;},function(err){alert('Error:'+err);});}functiontakePhoto(){if(!('ImageCapture'inwindow)){alert('ImageCaptureisnotavailable');return;}if(!theStream){alert('Grabthevideostreamfirst!');return;}vartheImageCapturer=newImageCapture(()[0]);().then(blob={vartheImageTag=("imageTag");=(blob);}).catch(err=alert('Error:'+err));}
RecordingMedia
recorder=newMediaRecorder(mediaStream,options)(mimeType)(interval)
Real-TimeCommunication
functiongetUserMedia(options,successCallback,failureCallback){varapi=||||||;if(api){(navigator)(options,successCallback,failureCallback);}}varpc1;varpc2;vartheStreamB;functiongetStream(){if(!!!!){alert('UserMediaAPInotsupported.');return;}varconstraints={video:true};getUserMedia(constraints,function(stream){addStreamToVideoTag(stream,'localVideo');//=||;pc1=newRTCPeerConnection(null);(stream);=event={if(==null)return;(newRTCIceCandidate());};pc2=newRTCPeerConnection(null);=event={theStreamB=;addStreamToVideoTag(,'remoteVideo');};=event={if(==null)return;(newRTCIceCandidate());};({offerToReceiveVideo:1}).then(desc={(desc);(desc);({offerToReceiveVideo:1});}).then(desc={(desc);(desc);}).catch(err={('createOffer()/createAnswer()failed'+err);});},function(err){alert('Error:'+err);});}functionaddStreamToVideoTag(stream,tag){varmediaControl=(tag);if('srcObject'inmediaControl){=stream;}elseif(){=stream;}else{=(||).createObjectURL(stream);}}
ShapeDetectionAPI

ShapeDetectionAPI是一组向Web应用程序公开底层系统的图像处理(如OCR(文本检测)、条形码/QR扫描或人脸检测功能)的服务。检测的可用性和质量因操作系统和硬件而异,API按原样公开这些服务。

functionwriteLog(message){constnewState=('p');=message;('target').appChild(newState);}functiondetectText(){if(!('TextDetector'inwindow)){alert('TextDetectorisnotavailable');return;}constfile=('file').files[0]if(!file){alert('Noimage-uploadafilefirst.');return;}('target').innerHTML='';constdetector=newTextDetector();createImageBitmap(file).then((image)=(image)).then((results)={if(){((result)={writeLog(`Detectedtext"${}"at(${()},${()})`);})}else{writeLog('Notextsdetected.');}}).catch((err)=writeLog('Textdetectionerror:'+err));}functiondetectBarcode(){if(!('BarcodeDetector'inwindow)){alert('BarcodeDetectorisnotavailable');return;}constfile=('file').files[0]if(!file){alert('Noimage-uploadafilefirst.');return;}('target').innerHTML='';constdetector=newBarcodeDetector();createImageBitmap(file).then((image)=(image)).then((results)={if(){((result)={writeLog(`Detectedtext"${}"at(${()},${()})`);})}else{writeLog('Nobarcodesdetected.');}}).catch((err)=writeLog('Barcodedetectionerror:'+err));}functiondetectFace(){if(!('FaceDetector'inwindow)){alert('FaceDetectorisnotavailable');return;}constfile=('file').files[0]if(!file){alert('Noimage-uploadafilefirst.');return;}('target').innerHTML='';constdetector=newFaceDetector();createImageBitmap(file).then((image)=(image)).then((results)={if(){((result)={writeLog(`Detectedfacewith${((l)=).join()}at(${()},${()})`);})}else{writeLog('Nofacesdetected.');}}).catch((err)=writeLog('Facedetectionerror:'+err));}
6.PWA与DeviceFeaturesNetworkTypeSpeed

NetworkInformationAPI允许Web应用程序读取当前网络类型以及基于客户端使用的底层连接技术假定的最大下行链路速度,同时还允许在网络类型发生更改时订阅通知。

functiongetConnection(){||||||;}functionupdateNetworkInfo(info){('networkType').innerHTML=;('effectiveNetworkType').innerHTML=;('downlinkMax').innerHTML=;}varinfo=getConnection();if(info){=function(event){updateNetworkInfo();}updateNetworkInfo(info);}
OnlineState

浏览器向Web应用程序公开网络连接可用性信息,以便应用程序可以做出正确反应,即在检测到离线情况时停止所有利用网络的操作并切换到缓存数据。

('online',listener)('offline',listener)
Vibration

VibrationAPI允许Web应用程序使用设备的内置振动(如果存在)。

functionvibrateSimple(){(200);}functionvibratePattern(){([100,200,200,200,500]);}
BatteryStatusAPI

BatteryStatusAPI允许Web应用程序获取有关设备电源、电池电量、预期充电或放电时间的信息。每当任何可用信息发生变化时,它还会公开事件。API允许应用程序根据功率级别打开或者关闭其低能效操作。

if('getBattery'innavigator||('battery'innavigator'Promise'inwindow)){vartarget=('target');functionhandleChange(change){vartimeBadge=newDate().toTimeString().split('')[0];varnewState=('p');=''+timeBadge+''+change+'.';(newState);}functiononChargingChange(){handleChange('Batterychargingchangedto'+(?'charging':'discharging')+'')}functiononChargingTimeChange(){handleChange('Batterychargingtimechangedto'++'s');}functiononDischargingTimeChange(){handleChange('Batterydischargingtimechangedto'++'s');}functiononLevelChange(){handleChange('Batterylevelchangedto'++'');}varbatteryPromise;if('getBattery'innavigator){batteryPromise=();}else{batteryPromise=();}(function(battery){('charging').innerHTML=?'charging':'discharging';('chargingTime').innerHTML=+'s';('dischargingTime').innerHTML=+'s';('level').innerHTML=;('chargingchange',onChargingChange);('chargingtimechange',onChargingTimeChange);('dischargingtimechange',onDischargingTimeChange);('levelchange',onLevelChange);});}
DeviceMemory

DeviceMemoryAPI允许Web应用程序根据安装的RAM内存的大小来评估设备的类别。出于性能原因,它可用于识别低端设备以提供精简、轻量级的网站体验。API提供的值并不暗示有多少内存实际可供应用程序使用,其目的仅用作设备类别指示。

('result').innerHTML=||'unknown'
7.PWA与OperatingSystem(操作系统)OfflineStorage

Web应用程序的离线存储功能的原型和标准化技术进行了多次迭代。第一次尝试要么只是一些简单的解决方法(例如:将数据存储在cookie中),要么需要额外的软件(例如:Flash或GoogleGears)。后来,WebSQL的想法(基本上是在浏览器中原生包含SQLite)被创造并在某些浏览器中实现,但后来由于标准化困难而被弃用。

目前至少有三种不同且独立的技术已标准化并可用。最简单的是WebStorage,一种键值字符串存储,允许Web应用程序持久地跨窗口存储数据(localStorage)或在单个浏览器选项卡中存储单个会话的数据(sessionStorage)。更复杂的IndexedDB是一个基于类似数据库结构的底层API,其中事务和游标通过索引进行迭代。而最新的CacheAPI是一个专门的解决方案,用于保存请求、响应对,主要在ServiceWorker实现中有用。

任何持久性存储(无论是localStorage、IndexedDB还是CacheAPI)中存储的数据的实际持久性都是由浏览器管理的,默认在内存压力情况下,可能会在未经最终用户同意的情况下被删除。为了解决这个问题,引入了StorageAPI,它为Web应用程序提供了一种在用户允许的情况下以完全可靠的方式存储数据的方法。

if('localStorage'inwindow||'sessionStorage'inwindow){varselectedEngine;varlogTarget=('target');varvalueInput=('value');varreloadInputValue=function(){(selectedEngine,window[selectedEngine].getItem('myKey'))=window[selectedEngine].getItem('myKey')||'';}varselectEngine=function(engine){selectedEngine=engine;reloadInputValue();};functionhandleChange(change){vartimeBadge=newDate().toTimeString().split('')[0];varnewState=('p');=''+timeBadge+''+change+'.';(newState);}varradios=('fff;cursor:inherit;display:block;}
StorageQuotas

StorageQuotas用于通过GoogleChrome进行的,以允许Web应用程序查询系统当前使用的和可供应用程序使用的存储空间的大小。

最新的QuotaEstimationAPI还包括一种请求浏览器保留所存储数据的方法,否则这些数据将在系统发出内存压力信号时被清除,请求此持久存储功能的权限可能由浏览器基于启发式授予(即GoogleChrome),或者可能需要明确的用户同意(即Firefox)。

旧的实现仅在带有webkit-前缀的Chrome中受支持,用于保持临时存储和持久存储之间的分离,并允许Web应用程序在需要时请求更多存储空间。

if('storage'innavigator'estimate'){().then(estimate={('usage').innerHTML=;('quota').innerHTML=;('percent').innerHTML=(*100/).toFixed(0);});}if('storage'innavigator'persisted'){().then(persisted={('persisted').innerHTML=persisted?'persisted':'notpersisted';});}functionrequestPersistence(){if('storage'innavigator'persist'){().then(persisted={('persisted').innerHTML=persisted?'persisted':'notpersisted';});}}
8.PWA与用户Input输入TouchGestures

传统意义上,Web依赖鼠标和键盘作为唯一的输入设备,而移动设备主要通过触摸控制。移动Web从一个有点棘手的问题开始,即将触摸事件转换为鼠标事件(例如mousedown)。

较新的HTML5方法是将touch作为一流的输入方式,允许Web应用程序拦截和识别复杂的多点触摸手势、徒手绘图等。不幸的是,目前要么通过触摸事件,例如touchstart,这是供应商走的路线,或者通过由微软发起的更新、更通用的指针事件规范时,苹果公司后来将其标准化为事实上的解决方案。

functionstartDrag(e){==moveDrag;==function(){==null;==null;}varpos=[,];varthat=this;varorigin=getCoors(e);functionmoveDrag(e){varcurrentPos=getCoors(e);vardeltaX=currentPos[0]-origin[0];vardeltaY=currentPos[1]-origin[1];=(pos[0]+deltaX)+'px';=(pos[1]+deltaY)+'px';returnfalse;//cancelsscrolling}functiongetCoors(e){varcoors=[];if(){varthisTouch=[0];coors[0]=;coors[1]=;}else{coors[0]=;coors[1]=;}returncoors;}}varelements=('.test-element');[].(elements,function(element){==startDrag;});=function(){returnfalse;}
SpeechRecognition

WebSpeechAPI的语音识别部分允许授权的Web应用程序访问设备的麦克风并生成所录制语音的文字记录,从而使得Web应用程序可以使用语音作为输入和控制方法之一,类似于触摸或键盘。

从技术上讲,语音识别功能也可以通过访问麦克风并使用WebAudioAPI处理音频流来实现,采用这种方法的典型示例库是。

letrecognition=newSpeechRecognition()
Clipboard(CopyPaste)

ClipboardAPI为Web应用程序提供了一种对用户执行的剪切、复制和粘贴操作做出反应以及代表用户直接读取或写入系统剪贴板的方法。

有两种类型的剪贴板API可用,比如:较旧的同步式和较新的异步式。较新的API仅限于HTTPS,并且需要明确的用户权限才能进行粘贴操作,但截至2020年初在Safari中依然不可用。旧的API没有正确解决隐私问题,因此粘贴功能在大多数浏览器中不再起作用。

varlogTarget=('logTarget');functionuseAsyncApi(){('input[value=async]').checked;}functionlog(event){vartimeBadge=newDate().toTimeString().split('')[0];varnewInfo=('p');=''+timeBadge+''+event+'.';(newInfo);}functionperformCopyEmail(){varselection=();varemailLink=('.js-emaillink');if(useAsyncApi()){//剪切板().then(()=log('AsyncwriteTextsuccessful,"'++'"written')).catch(err=log('AsyncwriteTextfailedwitherror:"'+err+'"'));}else{();varrange=();(emailLink);(range);try{varsuccessful=('copy');varmsg=successful?'successful':'unsuccessful';log('Copyemailcommandwas'+msg);}catch(err){log('execCommandError',err);}();}}functionperformCutTextarea(){varcutTextarea=('.js-cuttextarea');if(useAsyncApi()){().then(()={log('AsyncwriteTextsuccessful,"'++'"written');='';}).catch(err=log('AsyncwriteTextfailedwitherror:"'+err+'"'));}else{varhasSelection=('cut');();try{varsuccessful=('cut');varmsg=successful?'successful':'unsuccessful';log('Cuttingtextcommandwas'+msg);}catch(err){log('execCommandError',err);}}}functionperformPaste(){varpasteTextarea=('.js-cuttextarea');if(useAsyncApi()){().then((text)={=text;log('AsyncreadTextsuccessful,"'+text+'"written');}).catch((err)=log('AsyncreadTextfailedwitherror:"'+err+'"'));}else{();try{varsuccessful=('paste');varmsg=successful?'successful':'unsuccessful';log('Pastingtextcommandwas'+msg);}catch(err){log('execCommandError',err);}}}//GetthebuttonsvarcutTextareaBtn=('.js-textareacutbtn');varcopyEmailBtn=('.js-emailcopybtn');varpasteTextareaBtn=('.js-textareapastebtn');//('click',performCopyEmail);('click',performCutTextarea);('click',performPaste);functionlogUserOperation(event){log('Userperformed'++':'+('text/plain')+'');}('cut',logUserOperation);('copy',logUserOperation);
PointingDeviceAdaptation

CSS4规范的交互媒体部分定义了媒体查询,允许Web应用程序根据用户与应用程序交互的方式更改其布局和用户界面。其允许识别浏览器的主指针(即鼠标、触摸、键盘),并决定它是细还是粗,以及是否可以使用“经典”界面(如平板电脑上的触摸)将鼠标悬停在元素上,以便界面可以缩小或放大,并启用悬停交互或相应地用替代方案替换。

@media(hover:hover){button:hover~button{font-size:x-small;}}@media(pointer:coarse){RRGGBB)=;}).catch(error={//handletheuserchoosingtoexiteyedroppermodewithoutaselection});});

下面是HTML内容:

divclass="column"pClickontheimagebelowtoactivatethedropper/pimgid="eyeDropperIcon"src="/images/"/pThehexcoloroftheselectedpixelisbspanid="colorCode"???/span/b/p/div
9.PWA与LocationPositionGeolocation

GeolocationAPI允许授权的Web应用程序访问设备提供的位置数据,其本身是使用GPS或从网络环境获得。除了一次性位置查询之外,还为应用程序提供了一种通知位置更改的方式。

vartarget=('target');varwatchId;functionappLocation(location,verb){verb=verb||'updated';varnewLocation=('p');='Location'+verb+':'++','++'';(newLocation);}if('geolocation'innavigator){('askButton').addEventListener('click',function(){//获取当前位置(function(location){appLocation(location,'fetched');});//更新位置watchId=(appLocation);});}else{='GeolocationAPInotsupported.';}
DevicePosition

第一代设备位置支持是DeviceOrientationAPI的一部分,其允许Web应用程序访问陀螺仪和指南针数据,以确定用户设备在所有三个维度上的静态方向。

基于GenericSensorAPI的新规范也存在方向传感器API(绝对和相对变体)。与之前的规范相反,它提供了以四元数表示的读数,这使得它直接与WebGL等绘图环境兼容。

if('DeviceOrientationEvent'inwindow){('deviceorientation',deviceOrientationHandler,false);}else{('logoContainer').innerText='DeviceOrientationAPInotsupported.';}functiondeviceOrientationHandler(eventData){vartiltLR=;vartiltFB=;vardir=;("doTiltLR").innerHTML=(tiltLR);("doTiltFB").innerHTML=(tiltFB);("doDirection").innerHTML=(dir);varlogo=("imgLogo");="rotate("+tiltLR+"deg)rotate3d(1,0,0,"+(tiltFB*-1)+"deg)";="rotate("+tiltLR+"deg)";="rotate("+tiltLR+"deg)rotate3d(1,0,0,"+(tiltFB*-1)+"deg)";}
DeviceMotion

第一代设备运动支持是DeviceOrientationAPI的一部分,其允许Web应用程序访问以加速度(以m/s2为单位)表示的加速度计数据和以事件形式提供的三个维度中每个维度的以旋转角度变化(以°/s为单位)表示的陀螺仪数据。

自2018年中期以来,针对每种传感器类型推出了基于通用传感器API的更新的单独规范。这些API可直接访问物理设备(加速计API、陀螺仪API和磁力计API)的读数以及通过组合物理传感器(线性加速传感器API和重力传感器API)的读数组成的高级融合传感器。

if('LinearAccelerationSensor'inwindow'Gyroscope'inwindow){('moApi').innerHTML='GenericSensorAPI';letlastReadingTimestamp;letaccelerometer=newLinearAccelerationSensor();('reading',e={if(lastReadingTimestamp){intervalHandler(());}lastReadingTimestamp=(accelerometer,'moAccel');});();if('GravitySensor'inwindow){letgravity=newGravitySensor();('reading',e=accelerationHandler(gravity,'moAccelGrav'));();}letgyroscope=newGyroscope();('reading',e=rotationHandler({alpha:,beta:,gamma:}));();}elseif('DeviceMotionEvent'inwindow){('moApi').innerHTML='DeviceMotionAPI';varonDeviceMotion=function(eventData){accelerationHandler(,'moAccel');accelerationHandler(,'moAccelGrav');rotationHandler();intervalHandler();}('devicemotion',onDeviceMotion,false);}else{('moApi').innerHTML='NoAccelerometerGyroscopeAPIavailable';}functionaccelerationHandler(acceleration,targetId){varinfo,xyz="[X,Y,Z]";info=("X",(3));info=("Y",(3));info=("Z",(3));(targetId).innerHTML=info;}functionrotationHandler(rotation){varinfo,xyz="[X,Y,Z]";info=("X",(3));info=("Y",(3));info=("Z",(3));("moRotation").innerHTML=info;}functionintervalHandler(interval){("moInterval").innerHTML=interval;}
10.ScreenOutputVirtualAugmentedReality

截至2020年初,对Web应用程序的虚拟和增强现实的支持有限且不一致,有两个可用的API,较旧的WebVRAPI可在某些浏览器中用于某些特定的VR环境,而较新的WebXR设备API试图以更通用的方式处理该主题,包括AR或混合现实设备,从2019年底开始将部署在基于Chromium的浏览器中。

两个API共享相同的基本概念,范围是允许授权的Web应用程序发现可用的VR/AR设备,与设备建立会话,读取准备正确渲染所需的特定于设备的几何数据,并将canvas元素作为可视层绑定到设备上。

通过这种方式,渲染细节由现有的画布接口(如WebGL上下文)处理,并且实现者通常将渲染本身委托给专门的库(如A-Frame)。

('startVRButton').addEventListener('click',function(){if(){checkForXR();}elseif(){checkForVR();}else{alert('WebXR/WebVRAPIsarenotsupported.');}});asyncfunctioncheckForXR(){if(!('immersive-vr')){alert('NoimmersiveVRdevicedetected');return;}constsession=('immersive-vr');if(!){throw'VRsupported,butnoVRinputsourcesavailable';}constresult=('result');=+'inputsourcesdetected';}asyncfunctioncheckForVR(){try{constdisplays=()if(!){throw'VRsupported,butnoVRdisplaysavailable';}constresult=('result');(function(display){letli=('li');=+'('++')';(li);})}catch(err){alert(err);}}
Fullscreen

FullscreenAPI允许Web应用程序以全屏模式显示自身或自身的一部分,而浏览器UI元素不可见,也是方向锁定的先决条件状态。

var$=(document);var$=function(selector){return[].((selector),0);}vartarget=$('#logTarget');functionlogChange(event){vartimeBadge=newDate().toTimeString().split('')[0];varnewState=('p');=''+timeBadge+''+event+'.';(newState);}
ScreenOrientationLock

ScreenOrientationAPI允许Web应用程序获取有关文档当前方向(纵向或横向)的信息,以及将屏幕方向锁定在请求的状态。

当前版本的规范在对象中完全定义了此功能。以前的版本在MicrosoftEdge中实现过一次,将方向锁定分离为。

var$=(document);varorientKey='orientation';if('mozOrientation'inscreen){orientKey='mozOrientation';}elseif('msOrientation'inscreen){orientKey='msOrientation';}vartarget=$('logTarget');vardevice=$('device');varorientationTypeLabel=$('orientationType');functionlogChange(event){vartimeBadge=newDate().toTimeString().split('')[0];varnewState=('p');=''+timeBadge+''+event+'.';(newState);}if(screen[orientKey]){functionupdate(){vartype=screen[orientKey].type||screen[orientKey];=type;varlandscape=('landscape')!==-1;if(landscape){='180px';='100px';}else{='100px';='180px';}varrotate=('secondary')===-1?0:180;varrotateStr='rotate('+rotate+'deg)';=rotateStr;=rotateStr;=rotateStr;}update();varonOrientationChange=null;if('onchange'inscreen[orientKey]){//newerAPIonOrientationChange=function(){logChange('Orientationchangedto'+screen[orientKey].type+'');update();};screen[orientKey].addEventListener('change',onOrientationChange);}elseif('onorientationchange'inscreen){//olderAPIonOrientationChange=function(){logChange('Orientationchangedto'+screen[orientKey]+'');update();};('orientationchange',onOrientationChange);}//browsersrequirefullscreenmodeinordertoobtaintheorientationlockvargoFullScreen=null;varexitFullScreen=null;if('requestFullscreen'){goFullScreen='requestFullscreen';exitFullScreen='exitFullscreen';}elseif('mozRequestFullScreen'){goFullScreen='mozRequestFullScreen';exitFullScreen='mozCancelFullScreen';}elseif('webkitRequestFullscreen'){goFullScreen='webkitRequestFullscreen';exitFullScreen='webkitExitFullscreen';}elseif('msRequestFullscreen'){goFullScreen='msRequestFullscreen';exitFullScreen='msExitFullscreen';}
WakeLock

只要应用程序持有该资源的锁,WakeLockAPI就允许Web应用程序防止屏幕或系统等资源变得不可用。API的目的是让用户或应用程序不间断地完成正在进行的长时间活动(例如导航或阅读)。

在某些浏览器中实验性的初始实现尝试只是一个可由应用程序控制的布尔标志,被认为过于公开而容易被滥用,而且过于含蓄。

自2019年中期起,提出了更明确的方法,并可以在“实验性Web平台功能”标志后面以及通过GoogleChrome中的OriginTrial来使用。它允许指定请求锁定的资源,尽管目前只有屏幕选项可用。当外部因素中断锁定时,API还允许订阅事件。

functionprintStatus(status){("status").innerHTML=status;}letwakeLockObj=null;functiontoggle(){if("keepAwake"inscreen){=!;printStatus(?'acquired':'notacquired');}elseif("wakeLock"innavigator){if(wakeLockObj){();wakeLockObj=null;printStatus('released');}else{printStatus('acquiring');('screen').then((wakeLock)={wakeLockObj=wakeLock;('release',()={printStatus('releasedexternally');wakeLockObj=null;})printStatus('acquired');}).catch((err)={(err);printStatus('failedtoacquire:'+);})}}}if("keepAwake"inscreen){("api").innerHTML='';printStatus('notacquired');}elseif("wakeLock"innavigator){("api").innerHTML='';printStatus('notacquired');}
PresentationFeatures

PresentationAPI的目的是让Web应用程序可以使用演示显示模式,用于呈现的显示器可以与浏览器正在使用的显示器相同,但也可以是外部显示设备。浏览器可以充当演示的发起者以及接收在演示显示器上外部发起的到演示的连接。

目前该API仅在Chrome和Opera、桌面版和Android上受支持。

=newPresentationRequest(presentationUrl)()('change',listener)
参考资料

版权声明:本站所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,不声明或保证其内容的正确性,如发现本站有涉嫌抄袭侵权/违法违规的内容。请举报,一经查实,本站将立刻删除。

相关推荐