1

I am trying to create a scatterplot with a zooming. The following code I have used in my angular application and its working till a certain extent when I run it in my local server. However putting the same code in Stackblitz, the zooming is not working. I want to achieve a zooming where the zooming is limited to just the values on the graph. There should be no zooming of the axis accept the value changes in both the axis. Something exactly like : http://bl.ocks.org/peterssonjonas/4a0e7cb8d23231243e0e .

Here in the example, on zooming, only the values are zoomed and the axis values changed correspondingly. It doesn't zoom the whole graph plot area. How do I achieve it? Here is my Stackblitz code: https://stackblitz.com/edit/angular-hu2thj

ANSWER : Finally I figure out the graph for this problem in case of any future reference:

import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
import * as d3 from 'd3';

@Component({
    selector: 'app-scatterplot',
    templateUrl: './scatterplot.component.html',
    styleUrls: ['./scatterplot.component.css']
})
export class ScatterplotComponent implements OnInit {
    @ViewChild('chart1') private chartContainer: ElementRef;
    dataValue = [{ x: "67", y: "188", },
    { x: "200", y: "163" },
    { x: "254", y: "241" },
    { x: "175", y: "241" },

    ];
    ngOnInit() {
        this.graph();
    }

    graph() {

        const element = this.chartContainer.nativeElement;
        var svgWidth = 400;
        var svgHeight = 400;

        var margin = { top: 30, right: 40, bottom: 50, left: 60 };

        var width = svgWidth - margin.left - margin.right;
        var height = svgHeight - margin.top - margin.bottom;

        var originalCircle = {
            "cx": -150,
            "cy": -15,
            "r": 20
        };


        var svgViewport = d3.select(element)
            .append('svg')
            .attr('width', svgWidth)
            .attr('height', svgHeight)

        // create scale objects
        var x = d3.scaleLinear()
            .domain([1, 500])
            .range([0, width]);

        var y = d3.scaleLinear()
            .domain([1, 500])
            .range([height, 0]);


        // create axis objects
        var xAxis = d3.axisBottom(x);
        var yAxis = d3.axisLeft(y);


        // Zoom Function
        var zoom = d3.zoom()
            .on("zoom", zoomFunction);



        // Inner Drawing Space
        var innerSpace = svgViewport.append("g")
            .attr("class", "inner_space")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .call(zoom);




        // append some dummy data
        var data = innerSpace.selectAll("circle")
            .data(this.dataValue)
            .enter().append("circle")
            .attr("class", "dot")
            .attr("cx", function (d) {
                return x(d.x)
                    ;
            })
            .attr("cy", function (d) {
                return y(d.y);
            })
            .attr("r", 2);

        // Draw Axis
        var gX = innerSpace.append("g")
            .attr("class", "axis")
            .attr("transform", "translate(0, " + height + ")")
            .call(xAxis);

        var gY = innerSpace.append("g")
            .attr("class", "axis axis--y")
            .call(yAxis);



        // append zoom area
        var view = innerSpace.append("rect")
            .attr("class", "zoom")
            .attr("width", width)
            .attr("height", height - 10)
            .attr("fill", "transparent")
            .attr("fill-opacity", 0.1)
            .call(zoom)

        function zoomFunction() {
            // create new scale ojects based on event
            var new_xScale = d3.event.transform.rescaleX(x)
            var new_yScale = d3.event.transform.rescaleY(y)
            console.log(d3.event.transform)

            // update axes
            gX.call(xAxis.scale(new_xScale));
            gY.call(yAxis.scale(new_yScale));

            // update circle
            data.attr("transform", d3.event.transform)
        };

    }
}
Udit Gogoi
  • 675
  • 2
  • 11
  • 28
  • in my browser the zoom/translate is as dead as a dodo. https://stackoverflow.com/questions/51897596/d3-js-v4-how-to-add-zoom-button-with-the-default-wheelmouse-zoom-behavior https://stackoverflow.com/questions/51562401/d3-slow-zoomable-heatmap/51563890#51563890 – rioV8 Aug 18 '18 at 18:50
  • Its working in my browser , I don't know how. But in stackblitz it's not showing – Udit Gogoi Aug 18 '18 at 18:52
  • @rioV8 I have tried one of the solution in the link you provided, but it is zooming the whole graph which I don't need. I just need to zoom the plot containing value. Both axis should not changed on zoomin – Udit Gogoi Aug 18 '18 at 18:59
  • try the code in my answer – rioV8 Aug 18 '18 at 19:12

1 Answers1

0

The problem on stackblitz is that d3.event is null.

Try this to zoom the points in your local server.

You need to add a clip path and animate the axis, see the second example (heatmap)

var svg = d3.select(element)
    .append("svg:svg")
    .attr("width", w + left_padding)
    .attr("height", h + top_padding);

var g = svg.append("g");
var zoom = d3.zoom().on("zoom", function () { 
        console.log("zoom", d3, d3.event);
        g.attr("transform", d3.event.transform);
    });

svg.call(zoom);

g.selectAll("circle")
    .data(this.dataValue)
    .enter().append("circle")
    .attr("class", "dot")
    .attr("cx", d => x(d.x) )
    .attr("cy", d => y(d.y) )
    .attr("r", 2);
rioV8
  • 24,506
  • 3
  • 32
  • 49