Turf is using geodesic buffer. You will never be able to get a round buffer on an EPSG 3857 map. You can always make a cartesian buffer but it will be quite wrong...
An example with EPSG 3857 using reproject library, jsts, proj4js and Leaflet below. You can also look at the demo. It's mainly useful in my opinion when using a local projection that preserve locally quite well distance, area and angle unlike here.
bundle.js
mentioned in the sample is a file generated from reproject library using npm run bundle
(you can also found it in the mentioned live demo)
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
<script src="https://unpkg.com/[email protected]/dist/jsts.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.5/proj4.min.js"></script>
<script src="bundle.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""/>
<style>
html, body {
height: 100%;
padding: 0;
margin: 0;
}
#map {
/* configure the size of the map */
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
// initialize Leaflet
var map = L.map('map').setView({lon: 2.18, lat: 46}, 8);
var epsg3857 = proj4.Proj("EPSG:3857");
var crss = {
"EPSG:3857": epsg3857
};
var pt = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [2.18, 46]
}
};
// Reproject geometry coordinates to EPSG 3857
var point3857geometry = reproject.reproject(pt.geometry, proj4.WGS84, epsg3857, crss);
// Convert GeoJSON geometry with EPSG 3857 coordinates to jsts geometry
var geojsonReader = new jsts.io.GeoJSONReader();
var ptJsts = geojsonReader.read(point3857geometry);
// Create a 40000 meters buffer in "local" projection 3857
var bufferPtJsts = ptJsts.buffer(40000);
// Write back the generate buffer to GeoJSON
var geojsonWriter = new jsts.io.GeoJSONWriter();
var bufferGeoJSON = geojsonWriter.write(bufferPtJsts, 32);
// Reproject geomtry of buffer to WGS84
var bufferWGS84 = reproject.reproject(bufferGeoJSON, epsg3857, proj4.WGS84, crss);
console.log(bufferWGS84);
// Copy input feature and change geometry to polygon buffer
var bufferFeature = JSON.parse(JSON.stringify(pt));
bufferFeature.geometry = bufferWGS84;
// Add GeoJSON as a Leaflet layer
var myLayer = L.geoJSON().addTo(map);
myLayer.addData(bufferFeature);
// add the OpenStreetMap tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
}).addTo(map);
// show the scale bar on the lower left corner
L.control.scale().addTo(map);
// show a marker on the map
L.marker({lon: 0, lat: 0}).bindPopup('The center of the world').addTo(map);
</script>
</body>
</html>