Charger le module
Les URL du CDN, les deux variantes de build, et l’API Handler complète.
Une nouvelle intégration devrait utiliser Saphere Scan v2. Ce qui suit documente le module v1 pour les produits qui le font déjà tourner.
Les deux builds
Le même widget est publié deux fois, et celui que vous chargez décide de la façon dont vous l’atteignez.
| Build | URL | Comment obtenir Handler |
|---|---|---|
| Script classique | https://cdn.saphere.ai/saphere-scan/v1/js/main.min.js | window.Handler, ou l’événement handler-ready |
| Module ES | https://cdn.saphere.ai/saphere-scan/v1/mjs/main.min.js | import { Handler } from … |
Les deux acceptent un paramètre de requête facultatif ?customizationId=<uuid>, qui applique une personnalisation configurée dans la console avant que vos propres options ne soient fusionnées par-dessus.
Les URL ci-dessus sont celles de la Production. Seul l’hôte change d’un environnement à l’autre ; les chemins sont identiques :
| Environnement | Base du CDN |
|---|---|
| Production | https://cdn.saphere.ai |
| Test | https://cdn.test.saphere.ai |
Comme en v2, c’est le CDN depuis lequel vous chargez qui décide de l’environnement contre lequel le module travaille. Environnements couvre le reste.
Le build en module ES
À préférer lorsque vous maîtrisez la page et pouvez utiliser des modules.
<script type="module">
import { Handler } from "https://cdn.saphere.ai/saphere-scan/v1/mjs/main.min.js"
Handler.load("#container", options)
</script>
Le build classique
Pour les pages qui ne peuvent pas utiliser de modules — une coquille Ionic, par exemple, où le script se trouve dans le gabarit de l’application.
<script src="https://cdn.saphere.ai/saphere-scan/v1/js/main.min.js"></script>
Le paquet pose window.Handler puis émet un événement handler-ready sur window.
Attendez l'événement, ne sondez pas
window.Handler n’est défini qu’une fois le script exécuté. Une balise de script plus bas dans la page qui le lirait immédiatement pourrait s’exécuter avant.
window.addEventListener("handler-ready", ({ detail: { Handler } }) => {
Handler.load("#container", options)
})
L’événement porte Handler dans son detail, de sorte que vous n’avez jamais à toucher à la variable globale.
L’API Handler
Tout y est statique. Il y a un widget par page.
Handler.load(target, options)
Monte le widget. Ne rend rien.
| Paramètre | Accepte |
|---|---|
target | Une chaîne de sélecteur CSS, ou un HTMLDivElement |
options | L’objet d’options — voir Options |
Le contenu du conteneur est remplacé. Donnez-lui une hauteur, car le widget le remplit.
Lève :
| Message | Cause |
|---|---|
SaphereScan is already loaded. | Un widget est déjà monté. Appelez destroy() d’abord, ou utilisez reload(). |
Module must be loaded in an HTMLDivElement | Le sélecteur n’a rien trouvé, ou a trouvé autre chose qu’un div. |
Bad integrator module options! | Vos options ont échoué à la validation. Le détail est écrit dans la console. |
Bad module options! | Les options fusionnées ont échoué à la validation — le plus souvent une personnalisation en conflit avec les vôtres. |
Lisez la console quand des options sont refusées
Les deux erreurs d’options écrivent la sortie de validation complète avant de lever. Le message levé seul ne dit pas quel champ était fautif ; l’entrée de console, si.Handler.destroy()
Asynchrone. Démonte le widget, vide le conteneur et libère la caméra.
await Handler.destroy()
Sans risque lorsque rien n’est monté — la fonction rend la main immédiatement.
Handler.reload(target, options)
Asynchrone. Équivaut à await destroy() puis load(...). C’est ainsi qu’on relance une mesure, ou qu’on applique de nouvelles options.
Accesseurs
| Accesseur | Type | Valeur |
|---|---|---|
Handler.isLoaded | boolean | Si un widget est actuellement monté |
Handler.langs | string[] | ["ar","de","en","es","fr","it","pl","pt","pt_BR","tr"] |
Handler.defaultModuleOptions | object | Les valeurs par défaut, avant fusion des vôtres |
Handler.isMobile | boolean | La détection d’appareil, telle que le widget la voit |
Handler.isMobile est utile pour la mise en page : sur un navigateur de bureau, on veut généralement contraindre le widget à une colonne au format téléphone plutôt que le laisser remplir une fenêtre large.
Une page complète
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0">
<title>Saphere Scan v1</title>
<style>
html, body { padding: 0; margin: 0; overflow: hidden; }
#container { height: 100vh; }
/* Sur un navigateur de bureau, garder le widget dans une colonne au format téléphone. */
#container:not(.mobile) { aspect-ratio: 9 / 16; margin: auto; }
</style>
</head>
<body>
<div id="container"></div>
<script type="module">
import { Handler } from "https://cdn.saphere.ai/saphere-scan/v1/mjs/main.min.js"
const container = document.getElementById("container")
const options = {
createMeasure: {
// Votre serveur crée la mesure et rend { id }.
// Ne placez jamais une clé d'API dans une page — voir l'avertissement ci-dessous.
strategy: "delegate",
url: "/api/saphere-measure"
},
onEvent: event => {
console.log(event.type, event)
if (event.type === "result")
console.log("variables:", event.variables)
},
allowLeave: true,
lang: "fr"
}
if (Handler.isMobile)
container.classList.add("mobile")
Handler.load(container, options)
</script>
</body>
</html>
La clé d'API n'a pas sa place dans la page
Les exemples v1 publiés montrent headers: { Authorization: "Bearer <apiKey>" } écrit directement dans la page. Cela place une habilitation qui ouvre tout votre compte, et qui ne se révoque qu’en désactivant le compte, dans tout ce qui peut lire votre JavaScript.
Pointez createMeasure.url vers un point d’accès de votre propre serveur, authentifiez-y votre utilisateur, et faites appeler l’API Saphere par ce point d’accès avec la clé. Voir Options pour les deux stratégies.
Servez la page en HTTPS ou depuis localhost. Les navigateurs refusent l’accès à la caméra sur une origine non sécurisée.