美文网首页
基础部分

基础部分

作者: 今天女朋友想我了没 | 来源:发表于2018-11-19 13:17 被阅读0次

    坐标系

    D3通过SVG画图,SVG的坐标系同HTML中的坐标系类似,都是以左上角作为坐标原点,向下向右为正延伸。

    坐标轴

    坐标轴的实现有多种方法,主要可以分为以下几种:

    • 连续性输入连续性输出:线性比例尺scalelinear,通过把domain中给定的范围通过线性关系映射到SVG中由range规定的指定范围
    • 连续性输入离散性输出:scaleQuantile将连续性的domain映射为离散的range块
    • 离散性输入离散性输出:scaleordinal将离散的domain映射为离散的range块
    • 离散性输入连续性输出:通过划分n个一定宽度的band,把domain中的离散的数据,每个数据作为一个band,映射到range中指定的区域

    坐标轴的绘制通过上述的各种映射,然后根据映射设置样式,如d3中的axisBottom()绘制在底部的坐标轴,还可以设置刻度的长度、数量等等,然后通过添加g元素,通过call回调来画出给定格式的坐标轴,轴通过path绘制,刻度通过d3中提供的line(“path generator“之一)进行绘制,刻度之下的标注通过text标签,各项的位置可以通过attr添加transform属性来添加translate进行微调。

    主要的图表元素

    例如矩形图中的rect、散点图中的circle都是SVG中的元素,在d3中通过selectAll("rect").data(dataset).enter().append("rect")这种方式来给各项创建的矩形绑定数据。
    .data会给所选择的元素分配数据,如果所给元素少于可分配数据的话,就会把数据存于placeholder,.enter返回代表需要增加的那些元素(已经绑定了placeholder数据)的selection,所以在后面接的append()创建元素一经创建都绑定了所给的数据。矩形元素的定位依靠x,y,其中x,y的数据需要与坐标轴进行绑定,就是通过上述的各种映射,计算出相应的在SVG图上的位置。

    在SVG中可以通过path路径来进行产生任意的graph,d3提供了path generator可以根据points数组为我们自动创建path所需的d属性字符串,两者结合,可以很轻松的创建复杂的图形,对于想饼图这种需要startangle、endangle,输入的数据只是一个数组,故先把数组转换为对应的[startangle,endangle]数组,然后通过弧生成器来绘制最终的饼图。

    Brush and Zoom

    刷子选定选区,zoom进行缩放,缩放的原理是将选中的选区映射到整个画布之中,相当于一种对画布的重新绘制。
    条形图、面积图和折线图的zoom采用的机制都比较类似。都是先调用zoom的各项API创建一个zoom behavior,
    zoom.extent()设置平移显示的视口范围,
    zoom.scaleExtent()设置缩放的倍数,
    zoom.translateExtent()设置可以平移的元素范围,
    zoom.on()声明监听器,处理鼠标手势发生时的进行的操作,

    在监听器处理程序之中,最主要的一步就是
    xScale.range([2*padding,width-2*padding].map(d => d3.event.transform.applyX(d)));这是对x轴的比例尺的range进行改写,
    d3.event.transform.applyX(d)返回的是转换之后的x轴坐标.对比例尺进行改写之后再重新绘制各个元素的位置达到缩放的效果。

    demo

    完整代码见 github

    • bar chart


      屏幕快照 2018-11-19 下午12.43.30.png
    //部分关键代码
    var svg = d3.select("#chart")
            .append("svg")
            .attr("id","column")
            .attr("width",width)
            .attr("height",height)
            .call(zoom);
      
        var xScale = d3.scaleBand()
            .domain(tumourid)
            .rangeRound([2*padding,width-2*padding]);
      
        var yScale = d3.scaleLinear()
            .domain([0,1.1*yAxisWidth])
            .range([height-3*padding,3*padding]);
      
        var xAxis = d3.axisBottom(xScale)
            .tickSize(0)
            .tickPadding(6)
            .tickValues(xScale.domain().filter(function(d,i){return !(i%10)}));
            
        var yAxis = d3.axisLeft(yScale).tickSize(0);
       //缩放操作
        function zoom(svg){
          const extent = [[2*padding,3*padding],[width-2*padding,height-3*padding]];
          svg.call(d3.zoom()
            .scaleExtent([1,20])
            .translateExtent(extent)
            .extent(extent)
            .on("zoom",zoomed));
          function zoomed(){
            xScale.range([2*padding,width-2*padding].map(d => d3.event.transform.applyX(d)));
            svg.select("#svgrects")
              .selectAll("rect")
              .attr("x",function(d){
                return xScale(d["ID "])+xScale.bandwidth()/2;
              })
              .attr("width",xScale.bandwidth());
            svg.select(".axis--x").call(xAxis);
          }
        }
    //缩放裁剪
        svg.append("defs").append("clipPath")
            .attr("id","myclip")
            .append("rect")
            .attr("x","40")
            .attr("y","0")
            .attr("width","600")
            .attr("height","500");
    
        function make_y_axis(){
          return d3.axisLeft(yScale);
        }
        svg.append("g")
            .attr("stroke","lightgray")
            .attr("stroke-opacity","0.1")
            .attr("shape-rendering","crispEdges")
            .call(make_y_axis()
             .tickSize(-width+4*padding,0,0)
             .tickFormat(""))
            .attr("transform","translate("+(2*padding)+",0)");
      
        svg.append("g")
            .attr("class","axis axis--x")
            .attr("clip-path","url(#myclip)")
            .attr("transform","translate(0,"+(height-3*padding)+")")
            .call(xAxis)
            .selectAll("text")
            .attr("transform","rotate(90)"+"translate("+(1.4*padding)+",0)")
        svg.append("text")
            .attr("fill","black")
            .attr("text-anchor","end")
            .attr("font-size",10)
            .attr("x",width-padding)
            .attr("y",height-2*padding)
            .text("肿瘤ID");
        
        svg.append("g")
            .attr("class","axis axis--y")
            .attr("transform","translate("+(2*padding)+",0)")
            .call(yAxis)
            .append("text")
            .attr("text-anchor","middle")
            .attr("font-size",10)
            .attr("fill","black")
            .attr("x",0)
            .attr("y",3*padding)
            .text(s);
        
        svg.selectAll("text")
            .attr("fill","black");
        var rects = svg.append("g")
            .attr("id","svgrects")
            .attr("clip-path","url(#myclip)")
            .selectAll("rect")
            .data(dataset)
            .enter()
            .append("rect")
            .attr("fill",document.getElementById("variablescolor").value)
            .attr("x",function(d){
              return xScale(d["ID "])+xScale.bandwidth()/2;
            })
            .attr("y",function(d){
              return yScale(d[s]);
            })
            .attr("width",xScale.bandwidth())
            .attr("height",function(d){
              return height-yScale(d[s])-3*padding;
            }) ;
    
    • scatter diagram


      屏幕快照 2018-11-19 下午1.12.32.png
    //部分关键代码
    var svg = d3.select("#chart")
            .append("svg")
            .attr("id","solid")
            .attr("width",width)
            .attr("height",height)
      
        var xScale = d3.scaleLinear()
            .domain([0,1.1*xAxisWidth])
            .range([2*padding,width-padding*2]);
      
        var yScale = d3.scaleLinear()
            .domain([0,1.1*yAxisWidth])
            .range([height-padding,padding]);
          var circle =svg.append("g")
            .attr("id","svgcircles")
            .attr("clip-path","url(#myclip)")
            .selectAll("circle")
            .data(dataset)
            .enter()
            .append("circle")
            .attr("fill",document.getElementById("variablescolor").value)
            .attr("cx",function(d){
              return xScale(d[xstring]);
            })
            .attr("cy",function(d){
              return yScale(d[ystring]);
            })
            .attr("r",document.getElementById("variablessize").value);
      
        var xAxis = d3.axisBottom(xScale).tickSize(0,0,0);
           
        var yAxis = d3.axisLeft(yScale).tickSize(0,0,0);
        
        function make_x_axis(){
          return d3.axisBottom(xScale);
        }
        function make_y_axis(){
          return d3.axisLeft(yScale);
        }
        svg.append("g")
          .attr("calss","grid grid--x")
          .attr("stroke","lightgray")
          .attr("stroke-opacity","0.1")
          .attr("shape-rendering","crispEdges")
          .call(make_x_axis()
            .tickSize(height-2*padding,0,0)
            .tickFormat("")
          )
          .attr("transform","translate(0,"+padding+")");
        svg.append("g")
        .attr("class","grid grid--y")
        .attr("stroke","lightgray")
        .attr("stroke-opacity","0.1")
        .attr("shape-rendering","crispEdges")
        .call(make_y_axis()
          .tickSize(-width+4*padding,0,0)
          .tickFormat("")
        )
        .attr("transform","translate("+(2*padding)+",0)");
        svg.append("g")
            .attr("class","axis axis--x")
            .attr("transform","translate(0,"+(height-padding)+")")
            .call(xAxis)
            .append("text")
            .attr("fill","black")
            .attr("text-anchor","end")
            .attr("font-size",10)
            .attr("x",width)
            .attr("y",0)
            .text(xstring);
        
        svg.append("g")
            .attr("class","axis axis--y")
            .attr("transform","translate("+(2*padding)+",0)")
            .call(yAxis)
            .append("text")
            .attr("fill","black")
            .attr("text-anchor","middle")
            .attr("font-size",10)
            .attr("x",0)
            .attr("y",padding)
            .text(ystring);
      
        svg.selectAll("text")
            .attr("fill","black");
       
        svg.append("defs").append("clipPath")
            .attr("id","myclip")
            .append("rect")
            .attr("x","40")
            .attr("y","20")
            .attr("width","420")
            .attr("height","460");
        var brush = d3.brush().on("end",brushended),
            idleTimeout,
            idleDelay = 350;
        svg.append("g")
            .attr("id","brush")
            .call(brush);
        d3.select(".overlay").attr("pointer-events","none");
        d3.select("svg")
        .on("mousedown",function(){
          d3.select(".overlay").attr("pointer-events","all");
        });
            
        function brushended(){
          var s = d3.event.selection;
          if(!s){
            if(!idleTimeout){
              return idleTimeout = setTimeout(idled,idleDelay);
            }
            xScale.domain([0,1.1*xAxisWidth]);
            yScale.domain([0,1.1*yAxisWidth]);
          }else{
            xScale.domain([s[0][0],s[1][0]].map(xScale.invert,xScale));
            yScale.domain([s[1][1],s[0][1]].map(yScale.invert,yScale));
            svg.select("#brush").call(brush.move,null);
          }
          d3.select(".overlay").attr("pointer-events","none");
          zoom();
        }
        function idled(){
          idleTimeout = null;
        }
        function zoom(){
          var t = svg.transition().duration(750);
          svg.select(".axis--x").transition(t).call(xAxis);
          svg.select(".axis--y").transition(t).call(yAxis);
          svg.select(".grid--x").transition(t).call(make_x_axis()
          .tickSize(height-2*padding,0,0)
          .tickFormat(""));
          svg.select(".grid--y").transition(t).call(make_y_axis()
          .tickSize(-width+4*padding,0,0)
          .tickFormat(""));
          d3.select("#svgcircles").selectAll("circle").transition(t)
              .attr("cx",function(d){return xScale(d[xstring]);})
              .attr("cy",function(d){return yScale(d[ystring]);});
        }
    

    相关文章

      网友评论

          本文标题:基础部分

          本文链接:https://www.haomeiwen.com/subject/dhbofqtx.html