J’ai une électrique donnée pour 470 km. En hiver sur autoroute, c’est plutôt 350. Sur un long trajet, la vraie question n’est pas “où sont les bornes” mais “combien d’arrêts, où, et est-ce que je passe avec ce qu’il me reste”.
Les apps qui répondent bien à ça sont soit payantes, soit surchargées d’options, soit elles me demandent un compte. Je voulais un truc simple : je tape une destination, je vois les bornes rapides CCS sur ma route, et j’ai les arrêts recommandés avec la conso hiver déjà prise en compte. Sur mon téléphone, sans backend à maintenir.
J’ai fait EV Finder. Une PWA Vue 3 qui ne parle qu’à des APIs publiques : OpenChargeMap pour les bornes, OSRM pour l’itinéraire, Photon pour l’autocomplétion d’adresses, OpenStreetMap pour les tuiles.
Ce que ça fait
- Affiche les bornes CCS le long du trajet, pas juste autour de moi
- Calcule les arrêts de recharge nécessaires et les place sur la carte
- Ajuste l’autonomie effective en mode hiver
- Envoie le trajet complet dans Google Maps avec la borne comme point de passage
- Fonctionne hors-ligne une fois les tuiles téléchargées (PWA)
Récupérer les bornes le long d’une route
OSRM me renvoie la géométrie de l’itinéraire, une liste de coordonnées. Interroger OpenChargeMap sur chaque point serait absurde. J’échantillonne donc environ 10 points répartis le long de l’itinéraire (un point sur dix, plus le dernier), je requête les bornes dans un rayon de 30 km autour de chacun, et je dédoublonne par ID.
// un point sur dix le long de la route, + le dernier
const step = Math.max(1, Math.floor(routeCoords.length / 10))
for (let i = 0; i < routeCoords.length; i += step) {
samplePoints.push(routeCoords[i])
}
// toujours inclure le point d'arrivée
if (samplePoints.at(-1) !== routeCoords.at(-1)) {
samplePoints.push(routeCoords.at(-1))
}
const allChargers = new Map()
for (const [lng, lat] of samplePoints) {
const data = await fetchOpenChargeMap({ lat, lng, distance: 30 })
for (const c of data) {
if (!allChargers.has(c.ID)) allChargers.set(c.ID, normalize(c))
}
}
Le filtre “sur ma route” garde ensuite les bornes à moins de 5 km du tracé.
Placer les arrêts de recharge
L’algorithme est glouton. Depuis ma position, il cherche la borne la plus loin que je peux atteindre avec l’autonomie restante, s’y arrête, repart avec une charge à 80 % (le palier utile sur une borne rapide DC), et recommence jusqu’à la destination.
Deux garde-fous : une marge de sécurité de 10 % (je ne descends jamais sous 10 % d’autonomie), et le facteur hiver. À 25 kWh/100 km au lieu de 19, l’autonomie utile tombe à 76 % de la valeur annoncée.
let position = 0
let range = autonomyLeft * 0.9 * winterFactor
while (position + range < totalDistance) {
const reachable = chargers.filter(
c => c.distanceFromStart > position && c.distanceFromStart <= position + range
)
const stop = reachable.at(-1) // la plus loin atteignable
if (!stop) break
stops.push(stop)
position = stop.distanceFromStart
range = maxAutonomy * 0.8 * 0.9 * winterFactor
}
Viser la borne la plus loin plutôt que la plus proche minimise le nombre d’arrêts. C’est ce qu’on veut sur un long trajet.
Envoyer le trajet dans Google Maps
Une fois la borne choisie, un bouton ouvre l’itinéraire dans l’app de navigation, avec la borne intégrée comme étape. Google Maps gère ça très bien via un paramètre waypoints :
`https://www.google.com/maps/dir/?api=1` +
`&origin=${origin.lat},${origin.lng}` +
`&destination=${dest.lat},${dest.lng}` +
`&waypoints=${charger.lat},${charger.lng}` +
`&travelmode=driving`
Apple Plans, en revanche, n’a aucun paramètre de point de passage dans son URL scheme. Ni l’ancien maps.apple.com, ni les Unified Map URLs récentes. Le bouton “Plans” route donc simplement vers la borne, et Google Maps reste l’option pour le trajet complet. J’ai perdu une soirée dessus avant de l’accepter.
La stack et le déploiement

Vue 3 en Composition API, Vite pour le build, Leaflet pour la carte, Workbox (via vite-plugin-pwa) pour l’offline. Aucun serveur : tout tourne dans le navigateur, la seule config est une clé API OpenChargeMap gratuite.
| Service | Usage | Cache |
|---|---|---|
| OpenChargeMap | Données des bornes | 5 min |
| OSRM | Calcul d’itinéraire | 1 heure |
| Photon | Autocomplétion | 1 jour |
| OpenStreetMap | Tuiles | 30 jours |
Un point à connaître : comme c’est une app côté client, la clé VITE_OPENCHARGE_API_KEY finit dans le bundle JavaScript au build. Elle est donc visible par qui inspecte le site. Les clés OpenChargeMap sont gratuites et à faible risque, mais mieux vaut en dédier une au projet.
Le déploiement se fait sur Netlify, build automatique au push, la clé reste dans les variables d’environnement du dashboard.
Code source
Le projet est sur GitHub : didlawowo/ev-charge-tracker.
Les morceaux intéressants :
src/composables/useChargers.js: fetch le long de la route et filtragesrc/composables/useTripPlanner.js: l’algorithme d’arrêts et le facteur hiversrc/utils.js: les deep-links Google Maps et Apple Plans
Ce que vous devez retenir
- Pour planifier une recharge, chercher les bornes réellement proches du tracé est plus utile que charger toutes celles d’une région.
- Un algorithme glouton qui choisit la borne atteignable la plus éloignée suffit déjà à produire un plan cohérent avec peu d’arrêts.
- Les marges de batterie et la consommation hivernale doivent entrer dans le calcul, sinon le trajet paraît optimal seulement sur le papier.
- Une application 100 % navigateur convient bien à ce cas, avec une architecture très légère.