2014-10-03 4 views
0

최근에 d3.js 작업을 시작했습니다. 대화 형 다중 선 그래프를 개발하려고합니다. 지금까지 내 작품에서 봐 주시기 바랍니다 : 나는 그것의 축에 대해 각각의 선 그래프에 드래그 동작을 구현하기 위해 노력하고 http://jsfiddle.net/dalapati/cdkn14j3/6/D3.js- 선 그래프에서 축을 동적으로 업데이트합니다.

data1 = [ 
        {"date": 1357717800000,"value": "5.6"}, 
        {"date": 1357718400000,"value": "5.6"}, 
        {"date": 1357719000000,"value": "6"}, 
        {"date": 1357719600000,"value": "5.1"}, 
        {"date": 1357720200000,"value": "5.3"}, 
        // {"date": 1357720800000,"value": "5.4"} 
      ]; 

    data2 = [ 
        {"date": 1357714800000,"value": "5.2"}, 
        {"date": 1357715400000,"value": "5.2"}, 
        {"date": 1357716000000,"value": "5.2"}, 
        {"date": 1357716600000,"value": "5.1"}, 
        {"date": 1357717200000,"value": "5.5"}, 
      ]; 

// date manipulation to format UTC to js Date obj   
    data1.forEach(function(d){ d.time = new Date(d.time * 1000);}); 
    data2.forEach(function(d){ d.time = new Date(d.time * 1000);}); 

// helpers and constants   
var margin = {"top": 50, "right": 50, "bottom": 50, "left": 100, "axis": 55}; 
var width = 1500 - margin.left - margin.right; 
var height = 580 - margin.top - margin.bottom; 
var timeFormat = d3.time.format("%X"); 

// find data range 
var findXMin = function(_data){ 
    return d3.min(_data, function(d){ 
     return Math.min(d.date); 
    }); 
} 

var findXMax = function(_data){ 
    return d3.max(_data, function(d){ 
     return Math.max(d.date); 
    }); 
} 

var findYMin = function(_data){ 
    return d3.min(_data, function(d){ 
     return Math.min(d.value); 
    }); 
} 

var findYMax = function(_data){ 
    return d3.max(_data, function(d){ 
     return Math.max(d.value); 
    }); 
} 

var x1Min = findXMin(data1); 
var x1Max = findXMax(data1); 

var x2Min = findXMin(data2); 
var x2Max = findXMax(data2); 

var y1Min = findYMin(data1); 
var y1Max = findYMax(data1); 

var y2Min = findYMin(data2); 
var y2Max = findYMax(data2); 

var yMin = (y1Min < y2Min) ? y1Min:y2Min; 
var yMax = (y1Max > y2Max) ? y1Max:y2Max; 

    // scales 
var x1Scale = d3.time.scale() 
        .domain([x1Min,x1Max]) 
        .range([0, width]); 
var x2Scale = d3.time.scale() 
        .domain([x2Min,x2Max]) 
        .range([0, width]); 
var yScale = d3.scale.linear() 
        .domain([yMin,yMax]).range([height, 0]); 

var renderXAxis = function(scale, className, tickFormat, index0, index1, orient){ 
    var axis = d3.svg.axis() 
       .scale(scale) 
       .orient(orient) 
       .ticks(5) 
       .tickPadding(5) 
       .tickFormat(tickFormat); 
     svg.append("g") 
       .attr("class", className) 
       .attr("transform", function() {       
         return "translate(" +index0+", " +index1+ ")";}) 
       .call(axis); 
} 

var renderYAxis = function(scale, className, tickFormat, index0, index1, orient){ 
    var axis = d3.svg.axis() 
       .scale(scale) 
       .orient(orient) 
       .ticks(5) 
       .tickPadding(5) 
       .tickFormat(tickFormat); 
     svg.append("g") 
       .attr("class", className) 
       .attr("transform", function(){       
         return "translate(" +index0+", " +index1+ ")";}) 
       .call(axis); 
// grid plot 
    svg.append("g") 
     .attr("class", "y grid") 
     .call(make_y_axis() 
     .tickSize(-width, 0, 0) 
     .tickFormat(""));      
} 

var make_y_axis = function() { 
          return d3.svg.axis() 
           .scale(yScale) 
           .orient("left") 
           .ticks(5) 
           .tickPadding(5); 
         };  

// Set up chart type 
// create a line function that can convert data into x and y points 
var line1 = d3.svg.line().interpolate("basis") 
       .x(function (d) { 
        return x1Scale(d.date); 
       }) 
       .y(function (d) { 
        return yScale(d.value); 
       }); 
var line2 = d3.svg.line().interpolate("basis") 
       .x(function (d) { 
        return x2Scale(d.date); 
       }) 
       .y(function (d) { 
        return yScale(d.value); 
       }); 

// Create Zoom feature 
var zoomBottom = d3.behavior.zoom() 
        .x(x1Scale) 
        .scaleExtent([1,10]); 
var zoom = d3.behavior.zoom() 
        .x(x2Scale) 
        .scaleExtent([1,10]) 
        .on("zoom",zoomed); 


// Create Drag behaviour 
var drag = d3.behavior.drag() 
      .origin(function(d){ 
       var t = d3.select(this); 
       return { 
        x: t.attr("x"), 
        y: t.attr("y") 
       }; 
      }) 
      .on("dragstart", dragstarted) 
      .on("drag", dragged) 
      .on("dragend", dragended); 


// create svg container 
var svg = d3.select('#chart') 
       .append("svg:svg") 
       .attr('width', width + margin.left + margin.right) 
       .attr('height', height + margin.top + margin.bottom) 
       .append("svg:g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 


var plot = svg.append("svg:rect") 
       .attr("width", width) 
       .attr("height", height) 
       .attr("class", "plot") 
       .call(zoom); 

//Draw Axes 
var x1Axis = renderXAxis(x1Scale, "x1Axis", timeFormat, 0, height, "bottom"); 

var x2Axis = renderXAxis(x2Scale, "x2Axis", timeFormat, 0, 0, "top"); 

var yAxis = renderYAxis(yScale, "yAxis", function(d){return d;}, 0, 0, "left"); 

// add lines 
// do this AFTER the axes above so that the line is above the tick-lines 
var clip = svg.append("svg:clipPath") 
        .attr("id", "clip") 
        .append("svg:rect") 
        .attr("x1Scale", 0) 
        .attr("x2Scale", 0) 
        .attr("yScale", 0) 
        .attr("width", width) 
        .attr("height", height); 

var chartBody = svg.append("g") 
     .attr("clip-path", "url(#clip)"); 

    chartBody.append("svg:path") 
     .datum(data1) 
     .attr("class", "data1") 
     .attr("d", line1(data1)) 
     .attr("cursor", "move") 
     .call(drag); 

    chartBody.append("svg:path") 
     .datum(data2) 
     .attr("class", "data2") 
     .attr("d", line2(data2)) 
     .attr("cursor", "move") 
     .call(drag); 

/************************** ADDING ZOOMING FEATURE****************************************/ 

function zoomed() { 
     zoomBottom.scale(zoom.scale()).translate(zoom.translate()); 
     d3.select(".x1Axis").remove(); 
     renderXAxis(x1Scale, "x1Axis", timeFormat, 0, height, "bottom"); 
     d3.select(".x2Axis").remove(); 
     renderXAxis(x2Scale, "x2Axis", timeFormat, 0, 0, "top"); 
     d3.select(".yAxis").remove(); 
     renderYAxis(yScale, "yAxis", function(d){return d;}, 0, 0, "left"); 
     svg.select(".data1").attr("d",line1(data1)); 
     svg.select(".data2").attr("d",line2(data2)); 
    } 

/***************** Adding Dragging feature*****************************************************/ 

function dragstarted(d){ 
    d3.event.sourceEvent.stopPropagation(); 
    //d3.event.preventDefault(); 
    //d3.select(this).attr('pointer-events', 'none'); 
    d3.select(this).classed("dragging", true); 
    console.log(d); 

} 

function dragged(d){ 
    var lineToMove = d3.event.x; 
    d3.select(this) 
     .transition() 
     .ease("linear") 
     .attr("transform", "translate(" +lineToMove+ ",0)"); 
    d3.select(".x1Axis").remove(); 
    renderXAxis(x1Scale, "x1Axis", timeFormat, lineToMove, height, "bottom"); 
    d3.select(".x2Axis").remove(); 
    renderXAxis(x2Scale, "x2Axis", timeFormat, lineToMove, 0, "top"); 
    d3.select(".yAxis").remove(); 
    renderYAxis(yScale, "yAxis", function(d){return d;}, 0, 0, "left");} 

function dragended(d){ 
    d3.select(this).classed("dragging", false); 
} 

. 특정 선 그래프에 끌기 동작을 구현할 수는 있었지만 동적으로 해당 축을 업데이트하는 방법을 모르겠습니다. 누구든지이 문제를 해결할 수있는 아이디어를 공유 할 수 있습니까? 미리 감사드립니다. 나는 완전히 다시 렌더링 할 것 업데이트 기능으로 각 축

:

+0

일반적인 코멘트로서, 나는 완전히 업데이트 기능으로 각 축을 다시 렌더링하지 않을 것입니다. 대신 필요에 따라 기존 등록 정보를 업데이트하고 축을 한 번 그립니다. axis.scale (scale) .tickFormat (tickFormat)과 같은 메서드를 사용하면 이들에 액세스 할 수 있습니다. 이렇게하면 효율성이 높아집니다. 그럼 d3.select (".x.axis"). transition(). duration (1600) .call (xAxis) –

+0

안녕하십니까, 답장을 보내 주셔서 감사합니다. 당신이받은 아이디어는 훌륭합니다. 하지만 여기서 버그를 보았습니다. 처음에는 특정 그래프를 드래그하면 해당 축을 업데이트하여 정상적으로 작동합니다. 나중에 전체 플롯에서 확대/축소를 적용하면 축이 원래 위치로 다시 재설정됩니다. 다음은 업데이트 된 Jsfiddle입니다. http://jsfiddle.net/dalapati/cdkn14j3/8/ – Dinesh

+0

그 문제에 대한 새로운 질문을 열 것입니다. 나는 그 문제를 모른다. –

답변

1

이것은 내가 문제를 해결하기 위해 준 총평이다. 대신 필요에 따라 기존 등록 정보를 업데이트하고 축을 한 번 그립니다.

axis.scale(scale).tickFormat(tickFormat)과 같은 방법으로 액세스 할 수 있습니다. 이렇게하면 효율성이 높아집니다. 그럼 당신은 다음과 같이 할 수 있습니다 : d3.select(".x.axis").transition().duration(1600).call(axis)

관련 문제