Meilleures Actions

Les conséquences de la guerre au Moyen-Orient se font désormais sentir très clairement sur les prix des carburants dans les stations-service françaises. Le blocage du détroit d’Ormuz perturbe le trafic mondial de pétrole, provoquant une flambée du prix du baril, et donc, par ricochet, l’augmentation des prix payés à la pompe par les consommateurs.

Depuis le début de la guerre déclenchée par les Etats-Unis et Israël contre l’Iran, le gazole a ainsi flambé de plus de 15 %, se vendant en moyenne à 2 euros le litre, lundi 9 mars, contre 1,72 euro le 27 février, selon les chiffres agrégés par le gouvernement. Le sans-plomb 95 frôle quant à lui 1,90 euro.

Voici une carte pour consulter les prix des différents carburants dans près de 10 000 stations-service françaises, en métropole et en Corse.

Prix moyen du gazole : .

Prix le moins élevé : .

Prix le plus élevé : .

Protomaps © OpenStreetMap

${(isMobile ? `Utilisez deux doigts pour zoomer et un seul pour déplacer la carte.` : `Utilisez la molette de votre souris pour zoomer et le clic gauche pour déplacer la carte.`) +  » Cliquez sur un point pour découvrir le prix de l’essence de cette station. »}

Source : data.gouv.fr.

`;
}

let selectedCarburant = « Gazole »;

function pointToComma(str) {
return String(str).replace(/./g, « , »);
}

function formatDuration(date) {
const now = new Date();
const diff = now – date;
const diffInMinutes = Math.round(diff / 60000);

if (diffInMinutes < 1) {
return « moins d’une minute »;
} else if (diffInMinutes < 60) {
return `${diffInMinutes} minute${diffInMinutes > 1 ? « s » : «  »}`;
} else if (diffInMinutes < 1440) {
const hours = Math.round(diffInMinutes / 60);
return `${hours} heure${hours > 1 ? « s » : «  »}`;
} else if (diffInMinutes < 43200) {
const days = Math.round(diffInMinutes / 1440);
return `${days} jour${days > 1 ? « s » : «  »}`;
} else {
const months = Math.round(diffInMinutes / 43200);
return `${months} mois`;
}
}

async function initMap() {
const data = await d3.csv(« https://assets-decodeurs.lemonde.fr/sheets/Y388p3LJbkykLV8t8IzqCrxsv7vqBw_3922.csv »);
const carburants = last_update;
const correspondance = await d3.csv(« https://assets-decodeurs.lemonde.fr/sheets/do7ejUU8V-98xRlCzWZHrUGqf9vWcg_3736.csv »);
const quantiles = await d3.csv(« https://assets-decodeurs.lemonde.fr/sheets/do7ejUU8V-98xRlCzWZHrUGqf9vWcg_3815.csv »);
const scaleIft = d3.scaleThreshold([0.25, 0.5, 1, 3, 5], [« #f7f7f7 », « #e7d4e8 », « #c2a5cf », « #9970ab », « #762a83 », « #40004b »]);
const scaleSeuil = d3.scaleThreshold([1, 2, 3, 4], [« #f2f0f7 », « #cbc9e2 », « #9e9ac8 », « #756bb1 », « #54278f »]);
const boundsMetropole = [
[-5.708196140596648, 41.159442862997096],
[10.502321973141084, 52.10689424982629],
];
const boundsReunion = [
[55.07775392654938, -21.44419066387674],
[55.964781099227224, -20.774491046214454],
];
const boundsGuyane = [
[-54.985916441461164, 1.860861476138673],
[-51.12804741318951, 5.636713160986992],
];
const boundsAntilles = [
[-63, 13.64581],
[-59, 17.3],
];
const boundsMayotte = [
[44.9, -13.1],
[45.4, -12.5],
];
const boundsPolynesie = [
[-150.01993671781142, -18.031020108402718],
[-149.03472792054333, -17.281704029832003],
];

let enrichedData = data;

let layerStationsServices;

if (enrichedData) {
hideSpinner();

let tooltip = d3.select(« .carte_carburant__tooltip »);

function fillTooltip({ x, y, object }) {
tooltip.classed(« tooltip–hidden », false);

// console.log(object);

const stationsCarburants = {
« Prix du gazole »: « Gazole »,
« Prix du SP95 »: « SP95 »,
« Prix du SP98 »: « SP98 »,
« Prix du GPL-c »: « GPL-c »,
« Prix du E85 »: « E85 »,
« Prix du E10 »: « E10 »,
};

const content = `

${object.nom1 || « Station service  » + object.adress}

${object.nom1 ? `

${object.adress}

` : «  »}

    ${Object.entries(stationsCarburants)
    .filter(([nomFormate, nomClef]) => object[« prix_ » + nomClef] && +object[« prix_ » + nomClef] > 0)
    .map(
    ([nomFormate, nomClef]) =>
    `

  • ${nomFormate} : ${pointToComma(object[« prix_ » + nomClef])} € (mis à jour il y a ${formatDuration(new Date(object[« maj_ » + nomClef]))})
  • `,
    )
    .join(«  »)}

`;

// Fill tooltip
tooltip.select(« .tooltipcontent »).attr(« aria-label », « Articles politiquess »).html(content);

tooltip.select(« .tooltipcross »).on(« click », onMouseOut);

// Display and translate tooltip
//console.log(« isMobile », isMobile);

if (isMobile) {
tooltip.classed(« tooltip–hidden », false).style(« bottom », 0).style(« left », 0);
} else {
tooltip.classed(« tooltip–hidden », false).style(« bottom », `${y}px`).style(« left », `${x}px`);
}
}

// Hide tooltip

function onMouseOut() {
// document.querySelector(‘canvas’).style.cursor= »unset »;

tooltip.classed(« tooltip–hidden », true);
}

const mapSettings = {
center: [4.7, 47],
zoom: 4,
minZoom: 1,
maxZoom: 12,
bearing: 0,
pitch: 0,
};

const themeUrl = isDark
? « https://assets-decodeurs.lemonde.fr/decodeurs/assets/protomaps/contrast_daltoniens_darkmode_fr_v0.0.5.json »
: « https://assets-decodeurs.lemonde.fr/decodeurs/assets/protomaps/contrast_daltoniens_fr_v0.0.5.json »;

const theme = await d3.json(themeUrl);

const map = new maplibregl.Map({
container: « carte_carburant »,
style: {
version: 8,
glyphs: « https://assets-decodeurs.lemonde.fr/decodeurs/assets/protomaps_fonts/{fontstack}/{range}.pbf »,
sources: {
protomaps: {
type: « vector »,
maxzoom: 15,
tiles: [« https://prd-protomap.8084.lemonde.io/20240111/{z}/{x}/{y}.mvt »],
},
},
layers: theme,
},
center: mapSettings.center,
zoom: mapSettings.zoom,
minZoom: mapSettings.minZoom,
maxZoom: mapSettings.maxZoom,
//pitch: mapSettings.pitch,
//bearing: mapSettings.bearing,
//maxBounds: mapSettings.bounds
});

const deckOverlay = new deck.MapboxOverlay({
onClick: ({ x, y, object }) => {
if (object == undefined) return onMouseOut();
const mapContainer = document.getElementById(« carte_carburant »);
const adjustedY = mapContainer.offsetHeight – y;
return object && fillTooltip({ x, y: adjustedY, object });
},
onDragStart: () => onMouseOut(),
onResize: () => onMouseOut(),
pickingRadius: isMobile ? 20 : 8,
});

window.addEventListener(« click », (event) => {
if (!event.target.closest(« .carte_carburant__tooltip ») && !event.target.closest(« canvas »)) {
onMouseOut();
}
});

// Add deck layer
map.addControl(deckOverlay);

let scale = new maplibregl.ScaleControl({
maxWidth: 80,
unit: « metric »,
});

map.addControl(scale);

// Enable exploration

map.boxZoom.disable();
map.keyboard.disable();
map.doubleClickZoom.disable();
map.touchZoomRotate.disable();
map.dragRotate.disable();
map.touchPitch.disable();
map.scrollZoom.enable();
map.boxZoom.enable();
map.touchZoomRotate.enable();
map.dragPan.enable();

map.fitBounds(boundsMetropole);

// map.flyTo({
// center: mapSettings.center,
// zoom: mapSettings.zoom + 0.2,
// speed: 0.25,
// curve: 0.2,
// });

map.addControl(new maplibregl.NavigationControl({ showCompass: false }), « top-left »);

// Render layerspolys
function render() {
const filteredCarburants = carburants.filter((d) => +d[« prix_ » + selectedCarburant] && +d[« prix_ » + selectedCarburant] > 0);
const mean = d3.mean(filteredCarburants, (d) => +d[« prix_ » + selectedCarburant]);
const std = d3.deviation(filteredCarburants, (d) => +d[« prix_ » + selectedCarburant]);
const bornes = [mean – 2 * std, mean – std, mean, mean + std, mean + 2 * std];

// console.log(
// d3.min(
// filteredCarburants,
// (d) => +d[« prix_ » + selectedCarburant],
// ),
// d3.max(
// filteredCarburants,
// (d) => +d[« prix_ » + selectedCarburant],
// ),
// );

layerStationsServices = new deck.ScatterplotLayer({
id: « layerStationsServices »,
data: filteredCarburants,
getPosition: (d) => [+d[« long »], +d[« lat »], 0],
getFillColor: (d) => {
const value = d3.interpolatePlasma(1 – (+d[« prix_ » + selectedCarburant] – bornes[0]) / (bornes[4] – bornes[0]));
const color = d3.color(value).rgb();
return [color.r, color.g, color.b, 200];
},
getRadius: 500,
radiusMinPixels: 3,
radiusMaxPixels: 10,
pickable: true,
});

deckOverlay.setProps({ layers: [layerStationsServices] });

const min = filteredCarburants[d3.minIndex(filteredCarburants, (d) => +d[« prix_ » + selectedCarburant])];
const max = filteredCarburants[d3.maxIndex(filteredCarburants, (d) => +d[« prix_ » + selectedCarburant])];

container.querySelector(« .statistics »).innerHTML = `
Prix moyen du ${selectedCarburant} : ${pointToComma(mean.toFixed(2))} €.
Prix le plus bas : ${pointToComma(min[« prix_ » + selectedCarburant].toFixed(2))} € ${min[« departement »] ? `(${min[« departement »]})` : «  »}.
Prix le plus élevé : ${pointToComma(max[« prix_ » + selectedCarburant].toFixed(2))} € ${max[« departement »] ? `(${max[« departement »]})` : «  »}.
`;

container.querySelectorAll(« .flyto-price »).forEach((el) => {
el.onclick = () => {
const long = el.getAttribute(« data-long »);
const lat = el.getAttribute(« data-lat »);
map.flyTo({
center: [long, lat],
zoom: 10,
});
};
});
}

// Render first view
render();

// Watch flyto

document.querySelectorAll(« .carte_carburant__flytobtn »).forEach((btn) => {
btn.onclick = () => {
const place = btn.getAttribute(« data-attr »);
switch (place) {
case « reset »:
map.fitBounds(boundsMetropole, {
animate: false,
});
break;
case « reunion »:
map.fitBounds(boundsReunion, {
center: [55.558823, -21.109403],
animate: false,
});

break;
case « guyane »:
map.fitBounds(boundsGuyane, {
center: [-53.14191, 4.113978],
animate: false,
});

break;
case « antilles »:
map.fitBounds(boundsAntilles, {
center: [-61.235294, 15.125274],
animate: false,
});

break;
case « mayotte »:
map.fitBounds(boundsMayotte, {
center: [45.150284, -12.800424],
animate: false,
});

break;
case « polynesie »:
map.fitBounds(boundsPolynesie, {
animate: false,
});
break;
default:
map.fitBounds(boundsMetropole, {
animate: false,
});
break;
}
};
});

/* AUTOCOMPLETE*/

let max_n_to_display = 6;
let min_char_to_search = 1;
let format_to_search = slugify;
let no_results_message = « Aucun résultat avec cette recherche »;

const reset_func = () => {
console.log(« reset »);
};
const func_to_treat_result_donnees = (result) => {
map.flyTo({
center: [result[« Longitude »], result[« Latitude »]],
zoom: 10,
});

// if (isMobile) {
// fillTooltip({ x: 0, y: 0, object: result });
// document.querySelector(
// « .carte_carburant__container .tooltipcross »,
// ).onclick = () => {
// onMouseOut();
// };
// }
};
const dedupedData = Array.from(new Set(data.map((d) => d[« Ville »].trim().toLowerCase()))).map((ville) => {
return data.find((d) => d[« Ville »].trim().toLowerCase() === ville.trim().toLowerCase());
});
const get_text_in_data = (x) => x[« Ville »];

autocomplete_decodeurs(
// L’id du lmui-search
« ecoles-pesticides-search »,

// Les données dans lesquelles chercher
dedupedData,

// Une fonction qui s’execute quand on sélectionne un item, elle prend en argument
// l’objet sélectionné
func_to_treat_result_donnees,

// Une fonction qui s’execute quand on désélectionne / reset
reset_func,

// Une fonction qui sélectionne le texte à chercher dans le tableau (optionnel si vos données
// ne sont que du texte)
get_text_in_data,

// Nombre de choix dans le autocomplete, par défaut 5
max_n_to_display,

// Nombre de lettres avant le déclenchement de l’autocomplete, par défaut 3
min_char_to_search,

// Une fonction qui normalise les input pour la recherche, par défaut slugify, c’est à dire que la casse
// et les accents sont ignorés
format_to_search,

// Texte à afficher si aucun resultat, par défaut « Aucun résultat avec cette recherche »
no_results_message,
);

container.querySelector(« #carburant-select »).addEventListener(« change », (e) => {
selectedCarburant = e.target.value;
render();
});

const lastSearch = new Date();

async function autocomplete_communes_decodeurs(id_container, func_to_treat_result, func_to_reset, max_n_to_display = 5, no_results_message = « Aucun résultat avec cette recherche ») {
const get_search_value_in_data = (f) => {
return f.properties.label;
};
// OnSearch / OnResults
const onSearch = async (currentValue) => {
// Typical search
if (currentValue.replaceAll(/s/g, «  »).length < 3) return;
const q = currentValue.replaceAll(/s/g, « + »);
const api_communes = `https://data.geopf.fr/geocodage/search/?q=${q}&type=municipality&limit=${max_n_to_display}`;

const data = await fetch(api_communes);
const rep = await data.json();
const data_communes = rep.features;

return data_communes;
};
await _generic_autocomplete(id_container, get_search_value_in_data, onSearch, func_to_treat_result, func_to_reset, 3, no_results_message);
}

autocomplete_communes_decodeurs(
// L’id du lmui-search
« prix-essence-search »,

//Une fonction qui s’execute quand on sélectionne un item
(result) => {
map.flyTo({
center: result.geometry.coordinates,
zoom: 10,
});
},

// Une fonction qui s’execute quand on désélectionne / reset
reset_func,

// Nombre de choix dans le autocomplete, par défaut 5
max_n_to_display,

// Nombre de lettres avant le déclenchement de l’autocomplete, par défaut 3
min_char_to_search,

// Une fonction qui normalise les input pour la recherche, par défaut slugify,
// c’est à dire que la casse et les accents sont ignorés
format_to_search,

// Texte à afficher si aucun resultat, par défaut « Aucun résultat avec cette recherche »
no_results_message,
);
}
}

// const INIT_DELAY = 2000; // 2 secondes
document.addEventListener(« DOMContentLoaded », () => {
fillHtml();
initMap();
// setTimeout(() => {
// initMap();
// }, INIT_DELAY);
});
window.onresize = () => {
console.log(« bqsdjkbsqkdjbq », window.innerWidth <= 600, window.innerWidth);

isMobile = window.innerWidth <= 600;
};
}

initViz();

L’espace des contributions est réservé aux abonnés.

Abonnez-vous pour accéder à cet espace d’échange et contribuer à la discussion.

S’abonner
Share.