After creating the text, get its width with getBoundingClientRect. We can use node()
in D3 on a selection to get the DOM node. Since the text is shifted to the right, we’ll shift it back using half the text width.
(The string with backticks is a template string).
const textWidth = TEXT.node().getBoundingClientRect().width
TEXT.attr("transform", `translate(${-textWidth/2}, ${(height / 2 + 75)})`);
const MARGIN = {
LEFT: 80,
RIGHT: 80,
TOP: 30,
BOTTOM: 30
};
const RECT_HEIGHT = 50,
DOMAIN = [0, 14];
let width = $(window).width() - MARGIN.LEFT - MARGIN.RIGHT,
height = $(window).height() - MARGIN.TOP - MARGIN.BOTTOM;
let value = 0,
arrowPosition = 0;
const FORMAT = d3.format(".1f");
////////////////////////////////////////////////////////////
///////////////////////// SVG //////////////////////////////
////////////////////////////////////////////////////////////
const SVG = d3.select("#scale")
.append("svg")
.attr("width", width + MARGIN.LEFT + MARGIN.RIGHT)
.attr("height", height + MARGIN.TOP + MARGIN.BOTTOM);
const G = SVG.append("g")
.attr("transform", "translate(" + MARGIN.LEFT + "," + MARGIN.TOP + ")");
const RECT = G.append("rect")
.attr("x", 0)
.attr("y", height / 2 - (RECT_HEIGHT / 2))
.attr("width", width)
.attr("height", RECT_HEIGHT);
//Draw the triangle symbol
let triangle = d3.symbol().type(d3.symbolTriangle).size(300);
const TRIANGLE = G.append("path")
.attr("d", triangle)
.attr("transform", "translate(" + 0 + "," + (height / 2 + 40) + ")");
//pH text element
const TEXT = G.append("text")
.attr("id", "pH")
.text(FORMAT(value))
const textWidth = TEXT.node().getBoundingClientRect().width
TEXT.attr("transform", `translate(${-textWidth/2}, ${(height / 2 + 75)})`);
////////////////////////////////////////////////////////////
//////////////////////// Scale /////////////////////////////
////////////////////////////////////////////////////////////
const SCALE = d3.scaleLinear()
.domain([0, width])
.range(DOMAIN);
////////////////////////////////////////////////////////////
///////////////////// Event handler ////////////////////////
////////////////////////////////////////////////////////////
RECT.on("mousemove", (event) => {
let coordinates = d3.pointer(event);
const textWidth = TEXT.node().getBoundingClientRect().width
TRIANGLE.attr("transform", "translate(" + coordinates[0] + ", " + (height / 2 + 40) + ")");
TEXT.attr("transform", `translate(${-textWidth/2 + coordinates[0]}, ${(height / 2 + 75)})`);
TEXT.text(FORMAT(SCALE(coordinates[0])));
});
<div id="scale"></div>
<!--jQuery.js-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- d3.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.js" integrity="sha512-I54fxhTJwRigWTc3uNjgDzgii7LW+WJuyyA8kc6WaaZ7RQQNAf8bOEJLRNav7n/ca09MUwl5FptUukvqrOTUvQ==" crossorigin="anonymous"></script>
CLICK HERE to find out more related problems solutions.