(function() { // Chart design based on the recommendations of Stephen Few. Implementation // based on the work of Clint Ivy, Jamie Love, and Jason Davies. // http://projects.instantcognition.com/protovis/bulletchart/ d3.bullet = function() { var orient = "left", // TODO top & bottom reverse = false, duration = 3000, ranges = bulletRanges, // 指向函数 markers = bulletMarkers, // 指向函数 measures = bulletMeasures, // 指向函数 width = 380, height = 30, tickFormat = null; // For each small multiple… function bullet(g) { g.each( function(d, i) { var rangez = ranges.call(this, d, i).slice().sort(d3.descending), markerz = markers.call(this, d, i).slice().sort(d3.descending), measurez = measures.call(this, d, i).slice().sort(d3.descending), state = !!d["state"]?d["state"]:0, g = d3.select(this) // 柱状图 分组 .append("g") .attr("transform", "translate(75)"); debugger; // Compute the new x-scale. var x1 = d3.scale.linear() .domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) .range(reverse ? [width, 0] : [0, width]); // Retrieve the old x-scale, if this is an update. var x0 = this.__chart__ || d3.scale.linear() .domain([0, Infinity]) .range(x1.range()); // Stash the new scale. this.__chart__ = x1; // Derive width-scales from the x-scales. var w0 = bulletWidth(x0), w1 = bulletWidth(x1); // Update the range rects. var range = g.selectAll("rect.range") .data(rangez); range.enter().append("rect") .attr("class", function(d, i) { return "range s" + i; }) .attr("width", w0) .attr("height", height) .attr("x", reverse ? x0 : 0) .transition() .duration(0) .attr("width", w1) .attr("x", reverse ? x1 : 0); range.transition() .duration(0) .attr("x", reverse ? x1 : 0) .attr("width", w1) .attr("height", height); // // 判断状态; var measureNum = markerz[0]; // for(var index=1;index= rangeNum){ // break; // } // } // var state = 4-index; // Update the measure rects. var measure = g.selectAll("rect.measure") .data(measurez); measure.enter().append("rect") .attr("class", function(d, i) { return "measure s" + i+"_"+state; }) .attr("width", w0) .attr("height", height) .attr("x", reverse ? x0 : 0) .attr("y", 0) .transition() .duration(duration) .attr("width", w1) .attr("x", reverse ? x1 : 0); measure.transition() .duration(duration) .attr("width", w1) .attr("height", height) .attr("x", reverse ? x1 : 0) .attr("y", 0); // Update the marker lines. // var marker = g.selectAll("line.marker") // .data(markerz); // marker.enter().append("line") // .attr("class", "marker") // .attr("x1", x0) // .attr("x2", x0) // // .attr("y1", height / 6) // // .attr("y2", height * 5 / 6) // .attr("y1", height*0.025) // .attr("y2", height*0.95) // .transition() // .duration(duration) // .attr("x1", x1) // .attr("x2", x1); // marker.transition() // .duration(duration) // .attr("x1", x1) // .attr("x2", x1) // .attr("y1", height*0.025) // .attr("y2", height*0.95); // .attr("y1", height / 6) // .attr("y2", height * 5 / 6); // console.log("w1============"); // debugger; // 添加状态说明 var meaningState = g.selectAll("meaning.state") .data(measurez); meaningState.enter().append("text") .attr("display","none") .attr("class","meaning state") .attr("x", x1) .attr("transform", "translate(-80)") .attr("y", height*0.72) .text(function () { var txt; switch(state){ case 1 : txt = "轻度";break; case 2 : txt = "中度";break; case 3 : txt = "重度";break; default : txt = "";break; } return txt; }); // 添加数字 var meaningText = g.selectAll("meaning.text") .data(measurez); meaningText.enter().append("text") .attr("display","none") .attr("class","meaning text") .attr("x", x1) .attr("transform", "translate(8)") .attr("y", height*0.75) .text(function () { return measureNum; }) .transition() .call(function (){ setTimeout(function(){ $(".meaning.state,.meaning.text").fadeIn(duration*0.6); }, duration*0.8); }); // Compute the tick format. // var format = tickFormat || x1.tickFormat(8); // // Update the tick groups. // var tick = g.selectAll("g.tick") // .data(x1.ticks(3), function(d) { // return this.textContent || format(d); // }); // Initialize the ticks with the old scale, x0. // var tickEnter = tick.enter().append("g") // .attr("class", "tick") // .attr("transform", bulletTranslate(x0)) // .style("opacity", 1e-6); // tickEnter.append("line") // .attr("y1", height) // .attr("y2", height * 7 / 6); // tickEnter.append("text") // .attr("text-anchor", "middle") // .attr("dy", "1em") // .attr("y", height * 7 / 6) // .text(format); // // Transition the entering ticks to the new scale, x1. // tickEnter.transition() // .duration(duration) // .attr("transform", bulletTranslate(x1)) // .style("opacity", 1); // Transition the updating ticks to the new scale, x1. // var tickUpdate = tick.transition() // .duration(duration) // .attr("transform", bulletTranslate(x1)) // .style("opacity", 1); // tickUpdate.select("line") // .attr("y1", height) // .attr("y2", height * 7 / 6); // tickUpdate.select("text") // .attr("y", height * 7 / 6); // Transition the exiting ticks to the new scale, x1. // tick.exit().transition() // .duration(duration) // .attr("transform", bulletTranslate(x1)) // .style("opacity", 1e-6) // .remove(); } ); d3.timer.flush(); } // left, right, top, bottom bullet.orient = function(x) { if (!arguments.length) return orient; orient = x; reverse = orient == "right" || orient == "bottom"; return bullet; }; // ranges (bad, satisfactory, good) bullet.ranges = function(x) { if (!arguments.length) return ranges; ranges = x; return bullet; }; // markers (previous, goal) bullet.markers = function(x) { if (!arguments.length) return markers; markers = x; return bullet; }; // measures (actual, forecast) bullet.measures = function(x) { if (!arguments.length) return measures; measures = x; return bullet; }; bullet.width = function(x) { if (!arguments.length) return width; width = x*0.9; // 改变宽度 return bullet; }; bullet.height = function(x) { if (!arguments.length) return height; height = x; return bullet; }; bullet.tickFormat = function(x) { if (!arguments.length) return tickFormat; tickFormat = x; return bullet; }; bullet.duration = function(x) { if (!arguments.length) return duration; duration = x; return bullet; }; return bullet; }; function bulletRanges(d) { var ranges = []; var start = !!d['startPoint']?d['startPoint']:0; d.ranges.forEach(function (value, index) { var _value = Math.abs(value-start); _value = _value==0?100:_value; ranges[index] = _value; }); var endRange = ranges[ranges.length-1]; endRange += (!!d.state&&d.state)>0?(Math.abs(endRange-start)/ranges.length):0; ranges.push(endRange); return ranges; } function bulletMarkers(d) { return d.markers; } function bulletMeasures(d) { var measures = []; d.measures.forEach(function (value, index) { var _value = Math.abs(value); measures[index] = _value; }); return measures; } function bulletTranslate(x) { return function(d) { return "translate(" + x(d) + ",0)"; }; } function bulletWidth(x) { var x0 = x(0); return function(d) { return Math.abs(x(d) - x0); }; } })();