d3.js v4刷子缩放功能Brush & Zoom

刷子&缩放(Brush & Zoom)

源码: https://github.com/HK-Kevin/d...
demo:https://hk-kevin.github.io/d3...


原理:brush事件控制zoom的放缩.


源码分析:

let svg = d3.select("svg"),
   margin = {top :20,right:20,bottom:50,left:50},
   areaWidth = svg.attr("width") - margin.left-margin.right,
   areaHeight = svg.attr("height") - margin.top - margin.bottom,
   g = svg.append("g")
   .attr("transform",`translate(${margin.left},${margin.top})`)
   .attr("width",areaWidth)
   .attr("height",areaHeight)

  let xScale =d3.scaleLinear()
    .domain([0,22])
    .range([0,areaWidth]);

  let yScale = d3.scaleLinear()
    .domain([40,0])
    .range([0,areaHeight]) ;

  let xAxis = d3.axisBottom(xScale) ;

  let yAxis = d3.axisLeft(yScale)  ;

  let line = d3.line()
  .curve(d3.curveStepAfter)
  .x(function(d){
    return xScale(d.x)
  })
  .y(function (d) {
     return yScale(d.y)
  });

  let t =d3.transition()
       .duration(500)
       .ease(d3.easeLinear)
 let xGrooup = g.append("g")
   .attr("transform",`translate(0,${areaHeight})`)
   .call(xAxis)

 let yGroup =  g.append("g")
    .attr("transform",`translate(0,0)`)
    .call(yAxis)

    g.append("clipPath")
   .attr("id", "clip")
   .append("rect")
   .attr("width", areaWidth)
   .attr("height", areaHeight);

let updateLine = g.append("g")
   .attr("class","chart")
   .selectAll("line")
   .data(data)

 let enterLine = updateLine.enter();
 let exitLine = updateLine.exit();

 let path =  enterLine.append("path")
   .attr("clip-path", "url(#clip)")
   .attr("class","line")
   .attr("d",line)
   .attr("fill","none")
   .attr("stroke",0)
   .transition(t)
   .attr("stroke-width",2)
   .attr("stroke","green")

   exitLine.remove();
  let zoom = d3.zoom()
       .scaleExtent([1, 8])
       .translateExtent([[0,0], [areaWidth, areaHeight]])
       .on("zoom", zoomed);


  let zoomRect = svg.append("rect")
   .attr("width",areaWidth)
   .attr("height",areaHeight)
   .attr("fill","none")
   .attr("pointer-events","all")
   .call(zoom);

 let  brush = d3.brushX()
     .extent([[0, 0], [areaWidth, 20]])
     .on("brush end", brushed);

 let xBrush = d3.scaleLinear().range([0, areaWidth])
     .domain(xScale.domain());

 let xTop = d3.axisTop(xBrush);

 let brushBox = svg.append("g")
 .attr("transform",`translate(${margin.left},${margin.top})`)
       .attr("class", "brushBox");

       brushBox.append('g')
          .attr('fill','black')
          .call(xTop);

        brushBox.append("g")
          .attr("class", "brush")
          .attr("fill", 'red')
          .call(brush)
          .call(brush.move, xScale.range())
          .selectAll("rect")
          .attr("width", areaWidth)
          .attr("height", 20);




 function zoomed() {
     let t = d3.event.transform.rescaleX(xScale)
     xGrooup.call(xAxis.scale(t))
     g.select("path.line").attr("d", line.x(function(d){
       return t(d.x)}))
     brushBox.select(".brush").call(brush.move,xScale.range().map(d3.event.transform.invertX,d3.event.transform))
   }

   function brushed() {
        if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
        let s = d3.event.selection || xScale.range();
        xScale.domain(s.map(xBrush.invert, xBrush));
       zoomRect .call(zoom.transform, d3.zoomIdentity.scale(areaWidth / (s[1] - s[0]))
          .translate(-s[0], 0))
      }

你可能感兴趣的:(d3.js,数据可视化)