Accepted answer

See this fiddle:

The main issue with your code above is that you correctly changed the cx and cy attributes (which are specific to the svg:circle element) to x and y in the part where you appended the svg:text elements, but you didn't change them in the tick handler, which is where the iterative layout update happens:

force.on("tick", function() {
    // snip

    node.attr("x", function(d) { return d.x; })
        .attr("y", function(d) { return d.y; });

You also should change the selection-and-appending from

var node = vis.selectAll("circle.node")


var node = vis.selectAll("text.node")

Even though I don't think this makes any difference in the context of this code, it will eventually trip you up - in D3, as explained here, you generally use the pattern "select with a selector, add missing nodes that match this selector, remove extra nodes that match this selector". In your code, the selector and the nodes you add don't match, which is a conceptual issue even if it doesn't have any ramifications for your code as written. (I should note that I still find this pattern a bit confusing and weird. But at a minimum, following it will make your code more legible to other developers.)

Related Query

More Query from same tag