본문 바로가기
  • Let's go grab a data
Development/D3js

Scatter (svg) 그래프 그리기, Transition

by pub-lican-ai 2017. 4. 20.
반응형

Scatter (svg) 그래프 그리기, Transition


[다운로드]

http://d3js.org/download/   (d3.js)

http://jquery.com/ (jquery.js)


[index.html]

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8">

    <title>D3 Test</title>

    <script type="text/javascript" src="../javascripts/lib/d3.js"></script>

    <link rel="stylesheet" href="../stylesheets/style.css">

</head>

<body>

<button class="btn adddata">add data</button>

<button class="btn removedata">remove data</button>

<br><br>

<div id="demo"></div>

<br><br>


<script src="../javascripts/lib/jquery.min.js"></script>

<script type="text/javascript">

    JSONData = [

        { "id": 3, "created_at": "Sun May 05 2013", "amount": 12000},

        { "id": 1, "created_at": "Mon May 13 2013", "amount": 2000},

        { "id": 2, "created_at": "Thu Jun 06 2013", "amount": 17000},

        { "id": 4, "created_at": "Thu May 09 2013", "amount": 15000},

        { "id": 5, "created_at": "Mon Jul 01 2013", "amount": 16000}

    ];


    (function() {

        var data = JSONData.slice();

        //var format = d3.timeFormat("%a %b %d %Y"); //d3 v3.5

        var parseTime = d3.timeParse("%a %b %d %Y"); //d3 v4.0

        var amountFn = function(d) { return d.amount };

        //var dateFn = function(d) { return format.parse(d.created_at) }; //d3. v3.5

        var dateFn = function(d) { return parseTime(d.created_at) }; //d3 v4.0


        var x = d3.scaleTime()  //시간 단위로 들어오는 인자를 scale로 변환한 값 반환

            .range([10, 280])   //범위 10~280내에 어느 위치인지 비율적 값으로

            .domain(d3.extent(data, dateFn)); //domain은 데이터셋의 처음과 끝을 지정 range가 고정되어 있기 때문에 데이터값이 바뀔때마다 domain도 바뀌어야한다


        var y = d3.scaleLinear() //상수 값 단위로 들어오는 인자를 scale()로 변환한 값 반환

            .range([180, 10])    //범위 180~10내에 어느 위치인지 비율적 값으로 -> svg의 y축은 반대이다

            .domain(d3.extent(data, amountFn)); //extend는 domain의 argument로써 d3.min(data, amountFn), d3.max(data, amountFn)을 지칭함


        var svg = d3.select("#demo").append("svg:svg")

            .attr("width", 300)

            .attr("height", 200);


        var refreshGraph = function () {


            x.domain(d3.extent(data, dateFn));   //x축 domain 재설정

            y.domain(d3.extent(data, amountFn)); //y축 domain 재설정


            var circles = svg.selectAll("circle").data(data);


            circles.transition()  //기존에 있던 데이터는 4로 줄이고 domain을 바꾸는 transition을 넣음

                .attr("r", 4)

                .attr("cx", function(d) { return x(dateFn(d)) })

                .attr("cy", function(d) { return y(amountFn(d)) });



            circles.enter()  //enter는 데이터 바인딩 역할 circle을 생성하여 append함. refresh 시 새로운 데이터(아직 바인딩이 안된)에 대해서만 영향을 줌

            .append("svg:circle")

            .attr("r", 16)

            .attr("cx", function(d) { return x(dateFn(d)) })

            .attr("cy", function(d) { return y(amountFn(d)) })

            .style("stroke","#79A32B")

            .style("stroke-width","2px")

            .style("fill","transparent")

            .transition()

            .attr("r",4);


            circles.exit() //exit는 refresh 시 사라진 데이터에 대한 처리. 데이터를 가지고 있을 지 실제로 삭제할지

                .transition()

                .attr("r",10)

                .transition()

                .attr("r",0)

                .remove()

            };



        d3.selectAll(".adddata")

            .on("click", function() {

                var start = d3.min(data, dateFn);

                var end = d3.max(data, dateFn);

                var time = start.getTime() + Math.random() * (end.getTime() - start.getTime());

                var date = new Date(time);


                obj = {

                    'id': Math.floor(Math.random() * 70),

                    'amount': Math.floor(1000 + Math.random() * 20001),

                    'created_at': date.toDateString()

                };

                data.push(obj);

                refreshGraph();

            });


        d3.selectAll(".removedata")

            .on("click", function() {

                data.splice(Math.floor(Math.random()*data.length),1);

                refreshGraph();

            });


        refreshGraph()

    })();


</script>


</body>

</html>



반응형