CSSEIKOCS 2014-06-26
需求及解决思路:用一张背景图画出鱼骨,上面分若干鱼刺,每个鱼刺为一个div,div里也有一个表示指向关系的背景图,每根鱼刺上的div都会有三个状态,收起,半展开,全展开。里面的部分指标内容会根据需要隐藏或展现。里面的内容分为四种类型的指标:汇总类目项,类目项,比率,换算指标。每个指标会是一个小的矩型框,里面有文字和占比图等信息,这就需要用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%' }] } }) })
background-color: blue;background-color: yellow;<input type="button" value="变蓝" @click="changeColorT