<button id="zoom_in">+</button>
<button id="zoom_out">-</button>

app.css

.overlay {
	fill: none;
	pointer-events: all;
}
button {
	padding: 10px 20px;
}

app.js

var width = 960,
    height = 500;

var randomX = d3.randomUniform(width / 2, 80),
    randomY = d3.randomUniform(height / 2, 80);

var data = d3.range(2000).map(function() {
    return [randomX(), randomY()];
});

var zoom = d3.zoom().scaleExtent([1 / 4, 8]).on("zoom", zoomed);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .append("g")
    .attr('id', 'test')
    .call(zoom)
    .on("wheel.zoom", null);

svg.append("rect")
    .attr("class", "overlay")
    .attr("width", width)
    .attr("height", height);

svg.selectAll("circle")
    .data(data)
    .enter().append("circle")
    .attr("r", 2.5)
    .attr("transform", function(d) { return "translate(" + d + ")"; });

function zoomed() {
    var t = d3.zoomTransform(selection.node()); // ADDED
    svg.attr("transform",
        "translate(" + t.x + "," + t.y + ")" +
        "scale(" + t.k + ")"
    );
}

function interpolateZoom(translate, scale) {
    var self = this;
    return selection.transition().duration(50)
        .call(zoom.transform,
            d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale))
}

var selection = d3.select('#test');
console.log('selection:', selection.node());

function zoomClick() {
    console.log('TARGET:', d3.event.target)
    var clicked = d3.event.target,
        direction = 1,
        factor = 0.1,
        target_zoom = 1,
        center = [width / 2, height / 2],
        extent = zoom.scaleExtent(),
        translate = d3.zoomTransform(selection.node()), // ADDED
        translate0 = [],
        l = [],
        view = { x: translate.x, y: translate.y, k: translate.k };

    d3.event.preventDefault();
    direction = (this.id === 'zoom_in') ? 1 : -1;
    console.log('DIRECTiON:', direction);
    target_zoom = view.k * (1 + factor * direction);

    if (target_zoom < extent[0] || target_zoom > extent[1]) { return false; }

    translate0 = [(center[0] - view.x) / view.k, (center[1] - view.y) / view.k];
    view.k = target_zoom;
    l = [translate0[0] * view.k + view.x, translate0[1] * view.k + view.y];

    view.x += center[0] - l[0];
    view.y += center[1] - l[1];

    interpolateZoom([view.x, view.y], view.k);
}

d3.selectAll('button').on('click', zoomClick);