d3和弦图

效果图:
在这里插入图片描述
高亮效果:
在这里插入图片描述
在这里插入图片描述

//chord.js,使用时直接引入,调用
//引入依赖d3,color.js是我自己的配色方案,可以直接使用d3的配色方案,例:d3.schemeSet3
define(['d3.v5.min.js','../color.js',],function(d3,color){
	var relation = function(data,width,height){
	    //data传入是一个对象,包含{names(指传入的数据名称数组),matrix:数据关系拼成的二维矩阵}
	    //例:names=['北京','上海','广州','深圳','河北']
	    //matrix= [
         //  [1000, 3045, 4567, 1234, 3714],
         //  [3214, 2000, 2060, 124, 3234],
         //  [8761, 6545, 3000, 8045, 647],
         //  [3211, 1067, 3214, 4000, 1006],
         //  [2146, 1034, 6745, 4764, 5000]
       //];
        var colors = color;
        var outerR = Math.min(width, height) / 2-85
        var innerR = outerR-15
        var padAngle = 2 * Math.PI / 200
        var names=data.names
        var matrix = data.matrix
        var chords = d3.chord()
                       .padAngle(padAngle)(matrix)

        clearSvg();
        if(matrix.length){
          var svg = createSvg(width, height)
          var tooltip = d3.select(".body").append("span")
                          .attr("class","tooltip") //用于css设置类样式
                          .attr("opacity",0.0)
          drawGroups() // 绘制节点
          drawChords() // 绘制弦图
          drawTicks()
          drawLabels()
        }else {
          d3.select('body').append('div').attr("class","noData").html('暂无关联数据')
        }
       function createSvg(w, h) {
          return d3.select('.relation-box')
                   .append('svg')
                   .attr('width', w)
                   .attr('height', h)
                   .append('g')
                   .attr('transform', 'translate('+w/2+','+h/2+')')
      }

   function clearSvg(){
     d3.select('.body').html('')
   }

   function drawGroups() {
       var groups = chords.groups // 节点数组
       var maxVal = d3.max(groups, function(d){return d.value})

       var arc = d3.arc()
           .innerRadius(innerR)
           .outerRadius(outerR)

       svg.append('g')
           .attr('class', 'groups')
           .selectAll('g')
           .data(groups)
           .enter()
           .append('g')
           .attr('class', 'group')
           .append('path')
           .attr('d', function(d){
               return arc(d)
           })
           .on('mouseover', fade(0.1))
           .on('mouseout', fade(1))
           .attr('fill', function(_, i){ return colors[i]})
   }

   function fade(opacity){
     var tooltipOpacity;
     opacity==0.1?tooltipOpacity=1:tooltipOpacity=0
     return function(g,i){
       svg.selectAll(".chord path").filter(function(d){
         return d.source.index!=i&&d.target.index!=i;
       })
       // .transition()
       .style("opacity",opacity)
       tooltip.html(names[g.index])
         //设置tooltip的位置(left,top 相对于页面的距离)
         .style("left",d3.event.offsetX+"px")
         .style("top",d3.event.offsetY+"px")
         .style("opacity",tooltipOpacity);
     }
   }
   function fadeCurrent(opacity){
     var tooltipOpacity;
     opacity==0.1?tooltipOpacity=1:tooltipOpacity=0
     return function(g,i){
       svg.selectAll(".chord path")
       // .transition()
       .style("opacity",opacity)
       d3.select(this)
                  .style("opacity",1);
       tooltip.html(names[g.source.index]+"-"+names[g.target.index]+": "+g.source.value+"条")
         //设置tooltip的位置(left,top 相对于页面的距离)
         .style("left",d3.event.offsetX+"px")
         .style("top",d3.event.offsetY+"px")
         .style("opacity",tooltipOpacity);
     }
   }

   function drawChords() {
       var ribbon = d3.ribbon()
           .radius(innerR-5)
       svg.append('g')
           .attr('class', 'chord')
           .selectAll('path')
           .data(chords)
           .enter()
           .append('path')
           .attr('d', ribbon)
           .attr('fill', function(d){return  colors[d.source.index]})
           .attr('stroke', function(d){return d3.rgb(colors[d.source.index]).darker()})
           .on('mouseover', fadeCurrent(0.1))
           .on('mouseout', fadeCurrent(1))
   }

   function drawTicks() {
       d3.selectAll('.group')
           .append('g')
           .attr('class', 'ticks')
           .selectAll('line')
           .data(function(d){
             var value = d.value,
                 startAngle = d.startAngle
                 endAngle = d.endAngle
             var k = (endAngle - startAngle) / value
               return d3.range(0, value, 100).map(function(value){ return ({
                   text: value,
                   angle: d.startAngle + value * k,
               })})
           })
           .enter()
           .append('g')
           // .call(createRadialTicks)
   }

   function drawLabels() {
       svg.append('g')
           .selectAll('text')
           .data(chords.groups)
           .enter()
           .append('g')
           .call(setAttr, {
               fill: function(_, i){return colors[i]},
               transform: function(d){
                   var deg = rotateAngle(d)
                   var degRotate = deg-90;
                   var outerRT = outerR+5;
                   return 'rotate('+degRotate+')translate('+outerRT+', 0)'
               }
           })
           .append('text')
           .attr('dominant-baseline', 'middle')
           .text(function(d, i){return names[d.index]})
           .call(setAttr, {
               transform: function (d) {
                   var deg = rotateAngle(d)
                   var boxWidth = -this.getBBox().width
                   return deg > 180
                       ? 'rotate(180)translate('+boxWidth+', 0)'
                       : ''
               }
           })
   }
   function setAttr(ele, attrs) {
       for ( var index in Object.entries(attrs)) {
           ele.attr(Object.entries(attrs)[index][0], Object.entries(attrs)[index][1])
       }
   }
   function tsRadian2angle(radian) {
       return radian * 180 / Math.PI
   }
   // 文本旋转角度
   function rotateAngle(d) {
       return tsRadian2angle( (d.startAngle + d.endAngle) / 2 )
   }
  }
	return relation;
});

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值