Capacités des médias et des appareils du navigateur

Détection des capacités du pointeur sur tablette audio

Dans un contexte de tablette audio, réalisez une détection des capacités du pointeur : avec du contenu réel, des contrôles utilisables, un retour d’état clair et une mise en page adaptée à différentes tailles.

Capacités des médias et des appareils du navigateurDétection des capacités du pointeurHTMLCSSBrowser API
Après activation de JavaScript, ce cas peut être modifié, exécuté et enregistré. Code source fixe ci-dessous :
<!doctype html>
<html lang="fr" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Détection des capacités du pointeur sur tablette audio</title>
  <style>
    :root { --ink:#3a2419; --paper:#fbf3df; --accent:#c66a2d; --secondary:#b5c88d; --line:color-mix(in srgb, var(--ink) 18%, transparent); --shadow:0 24px 60px color-mix(in srgb, var(--ink) 16%, transparent); color-scheme:light; }
    * { box-sizing:border-box; }
    html { min-width:320px; background:var(--paper); }
    body { min-height:100vh; margin:0; overflow-x:hidden; color:var(--ink); font-family:Baskerville,"Songti SC",serif; background:linear-gradient(90deg,var(--paper) 0 72%,color-mix(in srgb,var(--secondary) 18%,var(--paper)) 72%); }
    button,input,select,textarea { color:inherit; font:inherit; }
    button,[role="button"],input,select,textarea { accent-color:var(--accent); }
    button { cursor:pointer; }
    button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible { outline:3px solid var(--accent); outline-offset:3px; }
    [hidden] { display:none !important; }
    @media (max-width:700px) { .mast h1 { line-height:1.08 !important; letter-spacing:-.035em !important; overflow-wrap:anywhere; } }
    @media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; } }
    .page{width:min(1200px,calc(100% - 38px));margin:auto;padding:76px 0}.mast{display:grid;grid-template-columns:2fr 1fr;gap:7vw;align-items:center;margin-bottom:44px}.mast h1{font-family:Baskerville,"Songti SC",serif;font-weight:800;font-size:clamp(48px,11vw,112px);line-height:.86;letter-spacing:-.06em;margin:0}.eyebrow{display:block;margin-bottom:22px;color:var(--accent);font:800 11px/1 ui-monospace,monospace;letter-spacing:.26em}.intro{max-width:46ch;margin-top:26px;font-size:17px;line-height:1.85}.scenario{align-self:end;padding-bottom:14px;border-bottom:5px solid var(--accent);font-weight:800}.demo{border-radius:0 60px 0 0;box-shadow:-16px 18px 0 color-mix(in srgb,var(--accent) 22%,transparent);position:relative;min-height:460px;overflow:hidden;padding:clamp(30px,6vw,72px);background:color-mix(in srgb,var(--paper) 92%,#fff)}@media(max-width:700px){.page{width:calc(100% - 22px);padding:30px 0}.mast{grid-template-columns:1fr}.demo{padding:20px}}
    .panel{padding:20px;border:1px solid color-mix(in srgb,var(--accent) 50%,transparent);border-radius:18px;background:color-mix(in srgb,var(--paper) 88%,transparent);box-shadow:inset 0 0 24px color-mix(in srgb,var(--accent) 7%,transparent)}.stack{display:grid;gap:16px}.row{display:flex;flex-wrap:wrap;gap:9px}.action{padding:11px 16px;border:1px solid var(--accent);border-radius:6px;color:var(--accent);background:transparent;box-shadow:0 0 14px color-mix(in srgb,var(--accent) 10%,transparent)}.action.primary,.action.is-active{color:var(--paper);background:var(--accent)}.status{min-height:24px;color:var(--secondary);text-shadow:0 0 10px currentColor}.metric{font-size:clamp(30px,7vw,64px);font-weight:900;text-shadow:0 0 18px color-mix(in srgb,var(--accent) 40%,transparent)}.muted{opacity:.7}.chip{padding:6px 9px;border:1px solid var(--secondary);border-radius:4px}.meter{height:7px;background:color-mix(in srgb,var(--accent) 15%,transparent)}.meter>i{display:block;height:100%;box-shadow:0 0 12px var(--accent);background:var(--accent)}
    .composition-studio{display:grid;gap:14px}.studio-ruler{display:flex;justify-content:space-between;padding:0 4px;color:color-mix(in srgb,var(--ink) 55%,transparent);font:700 11px/1 ui-monospace,monospace;letter-spacing:.14em}.studio-ruler::before{content:"01 / WORKING PROTOTYPE"}.studio-ruler::after{content:"360 · 768 · 1440"}.composition-studio .demo::after{content:"";position:absolute;right:18px;bottom:18px;width:24px;height:24px;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);pointer-events:none}
    .pointer-profiler{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(190px,.65fr);gap:14px}.pointer-profiler>header{grid-column:1/-1;display:grid;grid-template-columns:1fr auto;gap:16px;padding:18px;border-block:3px solid var(--ink)}.pointer-profiler h2{margin:.2em 0}.pointer-profiler header dl{display:flex;gap:8px;margin:0}.pointer-profiler header dl div{min-width:100px;padding:8px;border-left:1px solid var(--line)}.pointer-profiler header dd{margin:5px 0 0;font-weight:900}#pointerPad{position:relative;min-height:330px;overflow:hidden;border:1px solid var(--line);background:radial-gradient(circle at center,color-mix(in srgb,var(--secondary) 24%,var(--paper)),var(--paper));touch-action:none}#pointerPad>i{position:absolute;left:50%;top:50%;width:24px;aspect-ratio:1;border:3px solid var(--paper);border-radius:50%;background:var(--accent);box-shadow:0 0 0 2px var(--accent);transform:translate(-50%,-50%)}#pointerPad output{position:absolute;right:14px;top:14px;padding:7px;background:var(--ink);color:var(--paper)}#pointerPad p{position:absolute;left:18px;bottom:12px;max-width:330px}.pointer-profiler>aside{display:grid;align-content:start;gap:14px;padding:20px;border:1px solid var(--line)}.pointer-profiler>aside label{display:grid;grid-template-columns:1fr auto;gap:7px}.pointer-profiler>aside input{grid-column:1/-1}.pointer-profiler ol{display:grid;gap:5px;padding-left:18px;font-size:11px}@media(max-width:680px){.pointer-profiler{grid-template-columns:1fr}.pointer-profiler>header{grid-template-columns:1fr}.pointer-profiler header dl{flex-wrap:wrap}}.workflow-spatial{display:grid;gap:16px}.workflow-spatial>header{display:grid;grid-template-columns:1fr minmax(170px,.35fr) minmax(170px,.35fr);gap:18px;align-items:end;padding-bottom:16px;border-bottom:5px solid var(--ink)}.workflow-spatial h2{margin:.2em 0}.workflow-spatial header label{display:grid;grid-template-columns:1fr auto;gap:7px}.workflow-spatial header input{grid-column:1/-1;width:100%}.spatial-grid{display:grid;grid-template-columns:minmax(0,var(--spatial-width)) 20px minmax(180px,1fr);gap:0;align-items:stretch}.spatial-core{min-width:0;transform:scale(var(--spatial-zoom));transform-origin:top left;transition:transform .2s}.spatial-handle{display:grid;min-height:300px;place-items:center;border:0;border-inline:1px dashed var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent);cursor:col-resize}.spatial-grid>aside{display:grid;align-content:center;gap:14px;padding:22px;background:color-mix(in srgb,var(--secondary) 14%,var(--paper))}.spatial-grid>aside strong{font-size:clamp(24px,4vw,42px)}@media(max-width:900px){.workflow-spatial>header{grid-template-columns:1fr}.spatial-grid{order:-1;grid-template-columns:1fr}.spatial-handle{min-height:44px;cursor:row-resize}.spatial-core{transform:none}}
  </style>
</head>
<body data-aesthetic="magazine" data-composition="studio">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">magazine / détection des capacités du pointeur / INTERMEDIATE</span><h1>Détection des capacités du pointeur sur tablette audio</h1><p class="intro">Dans un contexte de tablette audio, réalisez une détection des capacités du pointeur : avec du contenu réel, des contrôles utilisables, un retour d’état clair et une mise en page adaptée à différentes tailles.</p></div><span class="scenario">Tablette audio</span></header>
    <div class="composition-studio"><div class="studio-ruler" aria-hidden="true"></div><section class="demo" aria-label="Zone interactive de détection des capacités du pointeur sur tablette audio"><div id="workflowSpatial" class="workflow-spatial" style="--spatial-width:64%;--spatial-zoom:1"><header><div><span class="eyebrow">Tablette audio SPATIAL CANVAS</span><h2>poste de réglage pour tablette audio</h2></div><label>Proportion des éléments détectés<input id="workflowSpatialWidth" type="range" min="38" max="82" value="64"><output id="workflowSpatialWidthValue">64%</output></label><label>Redimensionnement du contenu<input id="workflowSpatialZoom" type="range" min="80" max="120" value="100"><output id="workflowSpatialZoomValue">100%</output></label></header><div class="spatial-grid"><section id="workflowCore" class="workflow-core spatial-core"><!-- 11DZ_CORE_START:browser-media-device-pointer-profile --><div class="pointer-profiler"><header><span class="eyebrow">POINTER PROFILER</span><h2>Table de trajectoire du pointeur pour tablette audio</h2><dl><div><dt>Pointeur principal</dt><dd id="pointerPrimary">—</dd></div><div><dt>Capacité de survol</dt><dd id="pointerHover">—</dd></div><div><dt>Point de contact d’activité</dt><dd id="pointerActive">0</dd></div></dl></header><section id="pointerPad" tabindex="0" aria-label="Déplacer la souris, le stylet ou le doigt pour échantillonner le pointeur"><i id="pointerDot"></i><output id="pointerCoordinates">x 0 · y 0</output><p>Déplacez le pointeur dans cette zone ; les utilisateurs au clavier peuvent déplacer le point d’échantillonnage avec les touches fléchées.</p></section><aside><label>Conservation de la trajectoire<input id="pointerTrailLength" type="range" min="3" max="20" value="8" data-core-bridge="browser-media-device-pointer-profile"><output>8</output></label><button id="pointerClear" class="action" type="button">Effacer la trajectoire</button><ol id="pointerSamples"></ol></aside></div><!-- 11DZ_CORE_END --></section><input id="workflowSpatialHandle" class="spatial-handle" type="button" value="↔" aria-label="Faire glisser pour ajuster la largeur de l’aperçu du cas principal"><aside><strong>Vérification des autorisations de la tablette audio</strong><p>Le registre des capacités audio de la tablette audio et l’enregistrement local de la tablette audio seront réorganisés en fonction de la taille du canevas.</p><output id="workflowSpatialStatus">Largeur 64%, zoom 100%</output><input id="workflowSpatialApply" class="action primary" type="button" value="Capacité d’enregistrement"></aside></div></div><p id="status" class="status" role="status" aria-live="polite"></p></section></div>
  </main>
  <script>
    'use strict';
    const statusOutput = document.querySelector('#status');
    const announce = message => { statusOutput.textContent = message; };
    /* 11DZ_CORE_SCRIPT_START:browser-media-device-pointer-profile */
const pointerPad=document.querySelector('#pointerPad');const pointerDot=document.querySelector('#pointerDot');const pointerSamples=[];const activePointers=new Map();let pointerPosition={x:50,y:50};function describePointers(){document.querySelector('#pointerPrimary').textContent=matchMedia('(pointer:fine)').matches?'Fin':'Grossier ou absent';document.querySelector('#pointerHover').textContent=matchMedia('(hover:hover)').matches?'Pris en charge':'Non pris en charge';document.querySelector('#pointerActive').textContent=String(activePointers.size);}function samplePointer(type,pressure){const limit=Number(document.querySelector('#pointerTrailLength').value);pointerSamples.unshift({type,x:Math.round(pointerPosition.x),y:Math.round(pointerPosition.y),pressure:Math.round((pressure||0)*100)});pointerSamples.splice(limit);document.querySelector('#pointerSamples').replaceChildren(...pointerSamples.map(sample=>{const item=document.createElement('li');item.textContent=sample.type+' · '+sample.x+','+sample.y+' · '+sample.pressure+'%';return item;}));}function movePointer(clientX,clientY,type='keyboard',pressure=0){const rect=pointerPad.getBoundingClientRect();pointerPosition={x:Math.max(0,Math.min(100,(clientX-rect.left)/rect.width*100)),y:Math.max(0,Math.min(100,(clientY-rect.top)/rect.height*100))};pointerDot.style.left=pointerPosition.x+'%';pointerDot.style.top=pointerPosition.y+'%';document.querySelector('#pointerCoordinates').textContent='x '+Math.round(pointerPosition.x)+' · y '+Math.round(pointerPosition.y);samplePointer(type,pressure);}pointerPad.addEventListener('pointerdown',event=>{activePointers.set(event.pointerId,event.pointerType);pointerPad.setPointerCapture(event.pointerId);movePointer(event.clientX,event.clientY,event.pointerType,event.pressure);describePointers();});pointerPad.addEventListener('pointermove',event=>movePointer(event.clientX,event.clientY,event.pointerType,event.pressure));pointerPad.addEventListener('pointerup',event=>{activePointers.delete(event.pointerId);describePointers();});pointerPad.addEventListener('keydown',event=>{if(!['ArrowLeft','ArrowRight','ArrowUp','ArrowDown'].includes(event.key))return;event.preventDefault();const rect=pointerPad.getBoundingClientRect();const x=rect.left+rect.width*(pointerPosition.x+(event.key==='ArrowRight'?4:event.key==='ArrowLeft'?-4:0))/100;const y=rect.top+rect.height*(pointerPosition.y+(event.key==='ArrowDown'?4:event.key==='ArrowUp'?-4:0))/100;movePointer(x,y);});document.querySelector('#pointerTrailLength').addEventListener('input',event=>{event.currentTarget.nextElementSibling.textContent=event.currentTarget.value;});document.querySelector('#pointerClear').addEventListener('click',()=>{pointerSamples.length=0;document.querySelector('#pointerSamples').replaceChildren();announce('Trace du pointeur effacée');});describePointers();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"browser-media-device-pointer-profile","selector":"[data-core-bridge=\"browser-media-device-pointer-profile\"]","mode":"range","key":"ArrowRight"};const workflowBridgeCore=document.querySelector('#workflowCore');const workflowBridgeControl=workflowBridgeCore.querySelector(workflowBridgeSpec.selector);if(!workflowBridgeControl)throw new Error('Missing core bridge: '+workflowBridgeSpec.name);const workflowBridgeControlledId=workflowBridgeControl.getAttribute('aria-controls');const workflowBridgeControlled=workflowBridgeControlledId?document.getElementById(workflowBridgeControlledId):null;workflowBridgeCore.dataset.workflowBridge=workflowBridgeSpec.name;workflowBridgeCore.dataset.workflowVersion='0';function workflowBridgeSerialize(){const visualNode=workflowBridgeCore.firstElementChild||workflowBridgeCore;const visual=getComputedStyle(visualNode);const outputs=[...workflowBridgeCore.querySelectorAll('output,[role="status"],[aria-live],meter,progress')].map(node=>node.textContent.trim()+'|'+node.getAttribute('aria-valuenow')+'|'+node.getAttribute('value'));const canvas=[...workflowBridgeCore.querySelectorAll('canvas')].map(node=>{try{return node.toDataURL().slice(-160);}catch{return 'canvas-unavailable';}});return JSON.stringify({html:workflowBridgeCore.innerHTML,status:statusOutput.textContent,outputs,canvas,visual:[visual.display,visual.visibility,visual.opacity,visual.transform,visual.filter,visual.backgroundColor,visual.width,visual.height],scroll:workflowBridgeSpec.mode==='scroll'?workflowBridgeControl.scrollTop:null});}let workflowBridgeLastEffect=workflowBridgeSerialize();function workflowBridgeSummary(){const label=(workflowBridgeControl.getAttribute('aria-label')||workflowBridgeControl.textContent||workflowBridgeControl.value||workflowBridgeSpec.name).trim().replace(/\s+/g,' ').slice(0,72);return label+' · Version de base '+workflowBridgeCore.dataset.workflowVersion;}function workflowBridgeCommit(){const effect=workflowBridgeSerialize();if(effect===workflowBridgeLastEffect)return {changed:false,summary:workflowBridgeSummary()};workflowBridgeLastEffect=effect;workflowBridgeCore.dataset.workflowVersion=String(Number(workflowBridgeCore.dataset.workflowVersion||0)+1);return {changed:true,summary:workflowBridgeSummary()};}function workflowBridgeScheduleCommit(){queueMicrotask(workflowBridgeCommit);setTimeout(workflowBridgeCommit,0);}workflowBridgeControl.addEventListener("input",workflowBridgeScheduleCommit);workflowBridgeControl.addEventListener('change',workflowBridgeScheduleCommit);const workflowBridgeStateTargets=new Set(workflowBridgeCore.querySelectorAll('dialog'));if(workflowBridgeControlled&&workflowBridgeCore.contains(workflowBridgeControlled))workflowBridgeStateTargets.add(workflowBridgeControlled);workflowBridgeStateTargets.forEach(target=>['close','cancel','toggle'].forEach(eventName=>target.addEventListener(eventName,workflowBridgeScheduleCommit)));function workflowBridgeActivate(){workflowBridgeControl.focus();const step=Number(workflowBridgeControl.step)||1;const min=workflowBridgeControl.min===''?-Infinity:Number(workflowBridgeControl.min);const max=workflowBridgeControl.max===''?Infinity:Number(workflowBridgeControl.max);let next=Math.min(max,Math.max(min,(Number(workflowBridgeControl.value)||0)+step));if(next===Number(workflowBridgeControl.value))next=Math.max(min,Number(workflowBridgeControl.value)-step);workflowBridgeControl.value=String(next);workflowBridgeControl.dispatchEvent(new Event('input',{bubbles:true}));workflowBridgeControl.dispatchEvent(new Event('change',{bubbles:true}));const result=workflowBridgeCommit();setTimeout(workflowBridgeCommit,0);return result;}function workflowBridgeReset(){workflowBridgeCore.dataset.workflowVersion='0';workflowBridgeLastEffect=workflowBridgeSerialize();}
const workflowSpatial=document.querySelector('#workflowSpatial');const workflowSpatialCore=document.querySelector('#workflowCore');const workflowSpatialWidth=document.querySelector('#workflowSpatialWidth');const workflowSpatialZoom=document.querySelector('#workflowSpatialZoom');const workflowSpatialHandle=document.querySelector('#workflowSpatialHandle');const workflowSpatialState={width:64,zoom:1,dragging:false};function workflowSpatialDrive(){workflowSpatial.style.setProperty('--spatial-width',workflowSpatialState.width+'%');workflowSpatial.style.setProperty('--spatial-zoom',String(workflowSpatialState.zoom));workflowSpatialWidth.value=String(workflowSpatialState.width);workflowSpatialZoom.value=String(Math.round(workflowSpatialState.zoom*100));document.querySelector('#workflowSpatialWidthValue').textContent=workflowSpatialState.width+'%';document.querySelector('#workflowSpatialZoomValue').textContent=Math.round(workflowSpatialState.zoom*100)+'%';document.querySelector('#workflowSpatialStatus').textContent='largeur '+workflowSpatialState.width+'%,mise à l’échelle '+Math.round(workflowSpatialState.zoom*100)+'%';announce('Le canevas de la tablette audio a été réorganisé');}workflowSpatialWidth.addEventListener('input',()=>{workflowSpatialState.width=Number(workflowSpatialWidth.value);workflowSpatialDrive();});workflowSpatialZoom.addEventListener('input',()=>{workflowSpatialState.zoom=Number(workflowSpatialZoom.value)/100;workflowSpatialDrive();});workflowSpatialHandle.addEventListener('pointerdown',event=>{workflowSpatialState.dragging=true;workflowSpatialHandle.setPointerCapture(event.pointerId);});workflowSpatialHandle.addEventListener('pointermove',event=>{if(!workflowSpatialState.dragging)return;const rect=workflowSpatial.getBoundingClientRect();workflowSpatialState.width=Math.max(38,Math.min(82,Math.round((event.clientX-rect.left)/rect.width*100)));workflowSpatialDrive();});workflowSpatialHandle.addEventListener('pointerup',event=>{workflowSpatialState.dragging=false;workflowSpatialHandle.releasePointerCapture(event.pointerId);});workflowSpatialHandle.addEventListener('wheel',event=>{event.preventDefault();workflowSpatialState.zoom=Math.max(.8,Math.min(1.2,workflowSpatialState.zoom+(event.deltaY<0?.05:-.05)));workflowSpatialDrive();},{passive:false});workflowSpatialHandle.addEventListener('keydown',event=>{if(!['ArrowLeft','ArrowRight'].includes(event.key))return;event.preventDefault();workflowSpatialState.width=Math.max(38,Math.min(82,workflowSpatialState.width+(event.key==='ArrowRight'?2:-2)));workflowSpatialDrive();});document.querySelector('#workflowSpatialApply').addEventListener('click',()=>{const bridge=workflowBridgeActivate();document.querySelector('#workflowSpatialStatus').textContent='Capacité enregistrée · largeur '+workflowSpatialState.width+'%,mise à l’échelle '+Math.round(workflowSpatialState.zoom*100)+'% · '+bridge.summary;announce(document.querySelector('#workflowSpatialStatus').textContent);});workflowSpatialDrive();
workflowBridgeReset();
  </script>
</body>
</html>
Commentaires sur la pageVous avez découvert un problème ou avez une suggestion d’amélioration ?
Les fonctions de retour nécessitent l’utilisation de la version en ligne

Veuillez activer JavaScript dans la version en ligne avant de soumettre ; les fonctionnalités locales de l’outil ou du cas ne sont pas affectées.

Aller vers la version en ligne pour envoyer des commentaires