You have a conceptual problem here:
- Mapping an input (domain) to an output (range): that's the task of the scale.
- Formatting the number and the unit (if any) in the axis: that's the task of the axis generator
Thus, in your scale, you'll have to set the domain to accept the raw, actual data (that is, the data the way it is) you have:
var scale = d3.scaleLinear()
.domain([-10000, 10000])//the extent of your actual data
.range([min, max]);
Then, in the axis generator, you change the value in the display. Here, I'm simply dividing it by 1000 and adding "mm":
var axis = d3.axisBottom(scale)
.tickFormat(d => d / 1000 + "mm");
Note that I'm using D3 v4 in these snippets.
Here is a demo using these values: -7500, 500 and 4250. You can see that the circles are in the adequate position, but the axis shows the values in mm.
var data = [-7500, 500, 4250];
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 200);
var scale = d3.scaleLinear()
.domain([-10000, 10000])
.range([20, 480]);
var axis = d3.axisBottom(scale)
.tickFormat(d => d / 1000 + "mm");
var circles = svg.selectAll("foo")
.data(data)
.enter()
.append("circle")
.attr("r", 4)
.attr("fill", "teal")
.attr("cy", 40)
.attr("cx", d => scale(d));
var g = svg.append("g")
.attr("transform", "translate(0,60)")
.call(axis);
<script src="https://d3js.org/d3.v4.js"></script>