用CSS画鱼刺图

需求及解决思路:用一张背景图画出鱼骨,上面分若干鱼刺,每个鱼刺为一个div,div里也有一个表示指向关系的背景图,每根鱼刺上的div都会有三个状态,收起,半展开,全展开。里面的部分指标内容会根据需要隐藏或展现。里面的内容分为四种类型的指标:汇总类目项,类目项,比率,换算指标。每个指标会是一个小的矩型框,里面有文字和占比图等信息,这就需要用css实现,并控制其位置坐标。

背景图:

 用CSS画鱼刺图

鱼刺内容示例:

用CSS画鱼刺图

css代码:

/**鱼骨背景**/
.row-delimeter{position:relative;height:100px;}
.row-delimeter .bg{position:absolute;bottom:0;left:0;width:100%;height:100px}
.row-delimeter .bg{background:url("img/yu-ci/delimeter-bg.png") no-repeat 0 0}
/**鱼刺div框**/
.the-chart .card > .hd{text-align:center;background:#fff url("img/card-hd-bg.png") no-repeat 50% 30px;}
.the-chart .card > .hd > .title{position:relative;display:inline-block;border:1px solid #acacac;-webkit-border-radius:2px;border-radius:2px;padding:4px 16px;font-size:18px;background-color:#fff}
.the-chart .card > .hd .expand,.the-chart .card > .hd .shrink{position:absolute;top:50%;margin-top:-7px}
.the-chart .card > .hd .shrink{left:-30px}
.the-chart .card > .hd .expand{right:-30px}
.the-chart .row-1 .card > .hd{padding-bottom:10px}
.the-chart .row-2 .card > .hd{padding-top:10px;background-position:50% -2px}
.the-chart{background:#fff;width:1240px;margin:0 auto;margin-top:20px;margin-bottom:60px;}
.the-chart .col-1, .the-chart .col-2, .the-chart .col-3{width:390px;float:left;}
.the-chart .col-1 .card, .the-chart .col-2 .card, .the-chart .col-3 .card{margin:0 auto;margin-left:20px}
/**三种状态**/
.card.small .middle.box,.card.small .larger.box{display:none}
.card.small .small.box{display:block;height:242px;}
.card.middle .larger.box, .card.middle .small.box{display:none}
.card.middle .middle.box{display:block;height:556px}
.card.larger .middle.box,.card.larger .small.box{display:none}
.card.larger .larger.box{display:block;}
.card.larger >.bd{height:640px}
/**当不是收起状态,鱼骨上的鱼刺要变高,以便容下更多指标**/
.middle .row-1,.larger .row-1{background:url("img/yu-ci/row-1-bg.png") no-repeat 0 290px}
.sheng-chuang.larger .num-4 .card-summary{margin-bottom:82px !important}
/**当是收起状态时,隐藏收缩按钮**/
.card.small .shrink{display:none}
.card.small{width:198px;margin-left:70px !important;}
.card.small > .bd{min-height:242px}
.card.small .middle.box, .card.small .larger.box{display:none}
.card.small .small.box{display:block;height:242px;}
/**在鱼刺div中从最右边偏移10px,从而实现了指标框的精确定位**/
.card.small .small.box .items{right:10px;}
/**和下一个指标框的距离**/
.card.small .small.box .items .item{margin-bottom:20px}
/**三种状态的背景图**/
.small.sheng-chuang >.bd{background:#fff url("img/yu-ci/small-bg-1.png") no-repeat 0 0}
.middle.sheng-chuang >.bd{background:#fff url("img/yu-ci/middle-bg-1.png") no-repeat 0 0}
.larger.sheng-chuang >.bd{background:#fff url("img/yu-ci/larger-bg-1.png") no-repeat 0 0}

html结构代码:

<div class="row-1 clearfix">   <!--鱼刺上方-->
      
</div>
<div class="row-delimeter">          <!--鱼刺-->
       <div class="bg"></div>
</div>
<div class="row-2 clearfix"></div>   <!--鱼刺下方-->

完成了静态的鱼刺图后,并且有了切换三种状态的功能。接下来,就要从后台获取数据了,因为节点较多,一开始考虑按指标名字来用查找dom节点的方式来填充数据,这样后台返回一个hashMap就行了,但在ie下发现效率十分低,会暂时出现假死状态。

解决的办法,是将后台返回的数据变成有格式的json字符串,然后写一个解析该字符串的js对象,动态生成鱼刺div中的内容。

JS解析类:

var Render = function(elem, data) {
  this.$elem = $(elem)
  this.$elem.small = this.$elem.find('.box.small')
  this.$elem.middle = this.$elem.find('.box.middle')
  this.$elem.larger = this.$elem.find('.box.larger')
  this.data = data

  this.initialize()
  this.$elem.data('render', this)
}

Render.prototype = {
  initialize: function() {
    this.render()
  },

  render: function(type) {
    type = this.$elem.attr('data-status') || 'small'

    var data = this.data[type], content, method,
      elem = this.$elem[type]

    for (var key in data) {
      method = $.camelCase('render-' + key)

      if (method in this) {
        elem.find('.' + key).html(this[method](data[key]))
      }
    }
  },

  renderSummaries: function(data) {
    var content = [], c ,item

    for (var i = 0, len = data.length; i < len; i++) {
      c = [], item = data[i]

      c.push('<li class="num-' + (i + 1) + '">')
      c.push('<div class="card-summary">')
      c.push('<div class="box">')
      c.push('<h2 class="title">' + item.name + '</h2>')
      // c.push('<p class="count">' + item.value + '</p>')
      c.push('<p class="count">')
      c.push('<span style="width: 20px" class="progress"></span>')
      c.push('<em class="num">' + item.value + '</em>')
      c.push('</p>')
      c.push('</div>')
      c.push('</div>')
      c.push('</div>')
      c.push('</li>')

      content.push(c.join(''))
    }

    return content.join('')
  },

  renderItems: function(data) {
    var content = [], c,item

    for (var i = 0, len = data.length; i < len; i++) {
      c = [], item = data[i]
      c.push('<li class="num-' + (i + 1) + '">')
      c.push('<div class="item card-item">')
      c.push('<p><em class="name">' + item.name + '</em></p>')
      c.push('<p class="count">')
      c.push('<span style="width: 80px" class="progress"></span>')
      c.push('<em class="num">' + item.value + '</em>')
      c.push('</p>')
      c.push('</div>')
      c.push('</li>')

      content.push(c.join(''))
    }

    return content.join('')
  },

  renderRates: function(data) {
    var content = [], c,item

    for (var i = 0, len = data.length; i < len; i++) {
      c = [], item = data[i]
      c.push('<li class="num-' + (i + 1) + '">')
      c.push('<div class="card-rate">')
      c.push('<div class="inner">')
      c.push('<p class="title">' + item.name + '</p>')
      c.push('<p class="count">')
      c.push('<span style="width: 80px" class="progress"></span>')
      c.push('<em class="num">' + item.value + '</em>')
      c.push('</p>')
      c.push('</div>')
      c.push('</div>')
      c.push('</li>')

      content.push(c.join(''))
    }

    return content.join('')
  },

  renderTips: function(data) {
    var content = [], c,item

    for (var i = 0, len = data.length; i < len; i++) {
      c = [], item = data[i]
      c.push('<li class="num-' + (i + 1) + '">')
      c.push('<div class="card-tip">')
      c.push('<div class="inner">')
      c.push('<p class="title">' + item.name + ':</p>')
      c.push('<p class="percent">' + item.value + '</p>')
      c.push('</div>')
      c.push('</div>')
      c.push('</li>')

      content.push(c.join(''))
    }

    return content.join('')
  }
}
$(function() {
        window.shengChuang = new Render('.sheng-chuang', {
          small: {
            summaries: [{
                name: '广告总刊例值',
                value: 47088400  
            }],
            
            items: [{
              name: '这里是名称名称',
              value: 1788400
            }, {
              name: '这里是名称名称',
              value: 4788400
            }, {
              name: '这里是名称名称',
              value: 488400
            }]
          },
          
          middle: {
            summaries: [{
                name: '广告总刊例值1',
                value: 47088400  
            }, {
                name: '广告总刊例值2',
                value: 47088
            }, {
                name: '广告总刊例值3',
                value: 47088400  
            }, {
                name: '广告总刊例值4',
                value: 47088
            }, {
                name: '广告总刊例值5',
                value: 47088400  
            }],
            items: [{
              name: '这里是名称名称1',
              value: 1788400
            }, {
              name: '这里是名称名称2',
              value: 4788400
            }, {
              name: '这里是名称名称3',
              value: 488400
            }, {
              name: '这里是名称名称4',
              value: 4788400
            }]
          },
          
          larger: {
            summaries: [{
                name: '广告总刊例值1',
                value: 47088400  
            }, {
                name: '广告总刊例值2',
                value: 47088
            }, {
                name: '广告总刊例值3',
                value: 47088400  
            }, {
                name: '广告总刊例值4',
                value: 47088
            }, {
                name: '广告总刊例值5',
                value: 47088400  
            }],
            items: [{
              name: '这里是名称名称1',
              value: 1788400
            }, {
              name: '这里是名称名称2',
              value: 4788400
            }, {
              name: '这里是名称名称3',
              value: 488400
            }, {
              name: '这里是名称名称4',
              value: 4788400
            }],
            
            tips: [{
              name: '单终端开机次数1',
              value: '3.8'
            }, {
              name: '单终端开机次数2',
              value: '3.8'
            }, {
              name: '单终端开机次数3',
              value: '3.8'
            }, {
              name: '单终端开机次数4',
              value: '3.8'
            },{
              name: '单终端开机次数5',
              value: '3.8'
            }],
            
            rates: [{
              name: '升窗开启率1',
              value: '75.88%'
            }, {
              name: '升窗开启率2',
              value: '75.88%'
            }, {
              name: '升窗开启率3',
              value: '75.88%'
            }]
          }
        })
      })

相关推荐