2017-11-14 18 views
1

Angular 4 응용 프로그램에서 d3js V4 차트를 작성하려고합니다. 차트는 여러 데이터 집합을 별도의 선으로 표시합니다.d3js가 꺾은 선형 차트에서 확대/축소 작업을 수행합니다.

확대/축소가 올바르게 작동하는 방법을 알아낼 수 없습니다 (X 축에만 해당).

zoomed() 기능은 내가 왜 그 기능이 작동하지 않는지에 대한 설명과 함께 이미 시도한 모든 것입니다.

createChart() { 
    const element = this.chartContainer.nativeElement; 
    this.width = element.offsetWidth - this.margin.left - this.margin.right; 
    this.height = element.offsetHeight - this.margin.top - this.margin.bottom; 

    // canvas 
    const svg = d3.select(element).append('svg') 
       .attr('width', element.offsetWidth) 
       .attr('height', element.offsetHeight); 

    // chart plot area 
    this.chart = svg.append('g') 
       .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')'); 

    // domains 
    const xDomain = [this.from, this.to]; 
    const yDomain = [0, 100]; 

    // scales 
    this.xScale = d3.scaleTime().domain(xDomain).range([0, this.width]); 
    this.yScale = d3.scaleLinear().domain(yDomain).range([this.height, 0]); 

    // "data" function to draw lines 
    this.valueline = d3.line<TimeValueObject>() 
     .curve(d3.curveStepBefore) 
     .x((d) => this.xScale(d.time)) 
     .y((d) => this.yScale(d.value)); 

    // X Axis 
    this.xAxis = this.chart.append('g') 
     .attr('class', 'xaxis') 
     .attr('transform', 'translate(0,' + this.height + ')') 
     .call(d3.axisBottom(this.xScale) 
      .ticks(this.xTicks) 
      .tickFormat(function (d) { return moment.utc(d).format(this.timeFormat); })); 

    // Y Axis 
    this.yAxis = this.chart.append('g') 
     .attr('class', 'yaxis') 
     .call(d3.axisLeft(this.yScale) 
      .ticks(this.yTicks)); 

    // zoom 
    const zoom = d3.zoom() 
       .on('zoom', this.zoomed.bind(this)); 

    this.chart.call(zoom); 
} 

addData(myDataObject) { 
    // Add a data valueline path 
    this.chart.append('path') 
     .attr('class', 'line') 
     .attr('stroke', myDataObject.strokeStyle) 
     .attr('id', myDataObject.name) 
     .attr('d', this.valueline(myDataObject.data)); 
} 

zoomed() { 
    //KO: Zoom applied to whole graph in every direction. 
    //this.chart.attr('transform', d3.event.transform); 

    //KO: Zoom applied to whole graph 
    // this.chart 
    //  .attr('transform', 'translate(' + d3.event.transform.x + ',0) scale(' + d3.event.transform.k + ',1)'); 

    //KO: Zoom applied to data but data not redrawn. Shows pixellated garbage at high zoom 
    //Besides: when zoomed, the data expands beyond chart limits (Y axis on the left and chart right edge) 
    //for (let [key, value] of this.dataObjects) { 
    // this.chart.select('#' + key + '') 
    //  .attr('transform', 'translate(' + d3.event.transform.x + ',0) scale(' + d3.event.transform.k + ',1)'); 
    //} 

    //KO: zoom is "elastic": 
    // - On first mousewheel, nothing happens 
    // - On second mousewheel, graph zooms in the direction of previous mousewheel 
    // - Example: If I 'mousewheelup' 3 times in a row, I will have to 'mousewheeldown' 8 times to get back to zero zoom. The graph will keep zooming instead of unzooming on the 3 first 'mousewheeldown' 
    //Besides: when zoomed, the data expands beyond chart limits (Y axis on the left and chart right edge) 
    //for (let [key, value] of this.dataObjects) { 
    // this.chart.select('#' + key + '') 
    //  .attr('d', this.valueline(value.data)); 
    //} 

    //X Axis zoom 
    const t = d3.event.transform; 
    this.xScale = t.rescaleX(this.xScale); //if I comment this line, no zoom occurs whatsoever 
    //this.xAxis.call(d3.axisBottom(this.xScale)); //will cause 'elastic' axis zoom 
} 

서로 다른 코드 시도는 "공식적인"예를 기반으로합니다 https://github.com/d3/d3-zoom

답변

0

마지막으로 해결책을 발견했다.

d3 줌 이벤트 값은 초기 확대/축소에 대해 항상 이고 이전 확대/축소와 비교하여 주어지지 않는다는 것이 트릭입니다.

그래서, 첫째, 규모가 원래 규모를 변환하여 조정해야합니다

const t = d3.event.transform; 
this.xScale.domain(t.rescaleX(this.xScaleOriginal).domain()); 

→이


다음 원래 규모의 복사본을 생성했다는 x 축이 될 수 있습니다 다시 그려은 :

this.xAxisElement.call(this.xAxis); 

→은 별도의 변수 항목을 저장했다 : xA를


마지막으로, 데이터 라인이 그려 수 첨부 축 요소 d3.axisBottom() 함수의 결과 및 대 xAxisElement XIS :이 수정되지

for (let [key, value] of this.dataObjects) { 
    this.chart.select('#' + key + '') 
     .attr('d', this.valueline(value.data)); 
}