javascript - d3.js chemical tube bar chart -
i interested in creating liquid bar chart of sorts. pointers/dotted markers pulling off side shown.
22 april - latest code work dynamic data http://jsfiddle.net/nyeax/1855/
latest bar chart code http://jsfiddle.net/nyeax/1827/
latest cleaned water wave code http://jsfiddle.net/qh9x5/10331/
//i want strip down waterwave code http://jsfiddle.net/qh9x5/10091/
//progress chart http://jsfiddle.net/nyeax/1740/
latest base code bar chart. http://jsfiddle.net/nyeax/1822/
var $this = $("#checmicalbars"); var data = [{ "label": "rendering", "value": 90, "startcolor": "#c3da54", "endcolor": "#c1e500" }, { "label": "character design", "value": 95, "startcolor": "#e94adc", "endcolor": "#aae3dd" }, { "label": "sketching", "value": 80, "startcolor": "#c3da54", "endcolor": "#fa5283" }, { "label": "story boarding", "value": 90, "startcolor": "#e94adc", "endcolor": "#f83b03" }, { "label": "drawing", "value": 82, "startcolor": "#c3da54", "endcolor": "#f88504" }, { "label": "painting", "value": 90, "startcolor": "#e94adc", "endcolor": "#f7d200" }]; var h = 150; var w = 300; var options = { minlimit: 0, maxlimit: 100 } // setup scales var x = d3.scale.ordinal() .rangeroundbands([0, w], .1); var y = d3.scale.linear() .range([h, 0]); var xaxis = d3.svg.axis() .scale(this.x) .orient("bottom"); var yaxis = d3.svg.axis() .scale(this.y) .orient("left"); // setup scales // chart container var progresschart = d3.select($this[0]).append("svg") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(0,5)"); var barrectsholder = progresschart.append("g") .attr("class", "chart") .attr("transform", "translate(15,0)"); // chart container y.domain([options["minlimit"], options["maxlimit"]]); //__ bars var bar = barrectsholder.selectall("rect") .data(data); //__ enter bar.enter() .append("rect") .attr("class", "bar") .attr("y", h); //__ update bar .attr("y", h) .attr("height", 0) .style("fill", function(d){ return d.startcolor; }) .transition() .duration(2500) .style("fill", function(d){ return d.endcolor; }) .attr("width", 20) .attr("x", function(d, i) { return 30 * i; }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return h - y(d.value); }) //__ exit bar.exit() .transition() .duration(250) .attr("y", 0) .attr("height", 0) .remove(); //__ bars
i've merged 2 charts - watercode translated correctly if separate svg - code cleaned up/reviewed. ensuring pointers/labels adjust/adapt more/less data sets.
latest jsfiddle http://jsfiddle.net/nyeax/1843/
var $this = $("#checmicalbars"); var data = [{ "label": "rendering", "value": 90, "startcolor": "#c3da54", "endcolor": "#c1e500" }, { "label": "character design", "value": 95, "startcolor": "#e94adc", "endcolor": "#aae3dd" }, { "label": "sketching", "value": 80, "startcolor": "#c3da54", "endcolor": "#fa5283" }, { "label": "story boarding", "value": 90, "startcolor": "#e94adc", "endcolor": "#f83b03" }, { "label": "drawing", "value": 82, "startcolor": "#c3da54", "endcolor": "#f88504" }, { "label": "painting", "value": 90, "startcolor": "#e94adc", "endcolor": "#f7d200" }]; var h = 450; var w = 400; var barheight = 150; var barwidth = 180; var options = { minlimit: 0, maxlimit: 100 } // setup scales var x = d3.scale.ordinal() .rangeroundbands([0, barwidth], .1); var y = d3.scale.linear() .range([barheight, 0]); var xaxis = d3.svg.axis() .scale(this.x) .orient("bottom"); var yaxis = d3.svg.axis() .scale(this.y) .orient("left"); // setup scales // chart container var progresschart = d3.select($this[0]).append("svg") .attr("width", w) .attr("height", h) .append("g") .attr("transform", "translate(0,5)"); var barrectsholder = progresschart.append("g") .attr("class", "barrectsholder") .attr("transform", "translate(15,0)"); var labelsholder = progresschart.append("g") .attr("class", "labelsholder") .attr("transform", "translate(10,"+(barheight+ 20)+")"); var lineholder = progresschart.append("g") .attr("class", "lineholder") .attr("transform", "translate(25,"+(barheight+ 15)+")"); // chart container y.domain([options["minlimit"], options["maxlimit"]]); /* var gauge = barrectsholder .append("g") .attr("width", config.w) .attr("height", config.h) .append("g"); liquidbar(gauge, config); */ var bar = barrectsholder.selectall("svg") .data(data); bar.enter() .append("svg") .attr("class", function(d, i) { return "bar"+i; }) .attr("width", 20) .attr("x", function(d, i) { return 30 * i; }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return barheight - y(d.value); }) $.each(data, function( index, value ) { //alert( index + ": " + value ); var config = { w: 20, h: barheight, value: value.value, amplitude: 0.02, // wave height percentage of radius of wave circle. countperwidth: 1, // number of full waves per width of wave circle. risetime: 1000, // amount of time in milliseconds wave rise 0 it's final height. animatetime: 1000, // amount of time in milliseconds full wave enter wave circle. rise: true, // control if wave should rise 0 it's full height, or start @ it's full height. colortransition: 1000, colorbefore: value.startcolor, // color before of fill wave. colorafter: value.endcolor, // color after of fill wave. offset: 0 // amount offset wave. 0 = no offset. 1 = offset of 1 full wave. }; var gauge = barrectsholder.selectall("svg.bar"+index) liquidbar(gauge, config); }); /* //__ bars var bar = barrectsholder.selectall("rect") .data(data); //__ enter bar.enter() .append("rect") .attr("class", "bar") .attr("y", barheight); //__ update bar .attr("y", barheight) .attr("height", 0) .style("fill", function(d){ return d.startcolor; }) .transition() .duration(2500) .style("fill", function(d){ return d.endcolor; }) .attr("width", 20) .attr("x", function(d, i) { return 30 * i; }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return barheight - y(d.value); }) //__ exit bar.exit() .transition() .duration(250) .attr("y", 0) .attr("height", 0) .remove(); //__ bars */ //__ labels var labels = labelsholder.selectall("text") .data(data); labels.enter() .append("text") .attr("class", "barlabels") .attr("x", 200) .attr("y", function(d, i) { return 20 * i; }) .text(function(d) { return d.label; }) var lines = lineholder.selectall("text") .data(data); lines.enter() .append("line")// attach line .style("stroke-dasharray", ("3, 3")) .style("stroke", "black")// colour line .attr("x1", function(d, i) { return barwidth-(30 * (i+1)); })//x pos of 1st end of line .attr("y1", function(d, i) { return 20 * i; })//y pos of 1st end of line .attr("x2", function(d, i) { return barwidth; })//x pos of 2nd end of line .attr("y2", function(d, i) { return 20 * i; });//y pos of 2nd end of line var lineheights = 100; lines.enter() .append("line")// attach line .style("stroke-dasharray", ("3, 3")) .style("stroke", "black")// colour line .attr("x1", function(d, i) { return 30 * i; })//x pos of 1st end of line .attr("y1", function(d, i) { return lineheights - (20 * i); })//y pos of 1st end of line .attr("x2", function(d, i) { return 30 * i; })//x pos of 2nd end of line .attr("y2", function(d, i) { return -15; });//y pos of 2nd end of line function liquidbar(gauge, config) { var fillpercent = math.max(0, math.min(100, config.value)) / 100; var waveheightscale = d3.scale.linear() .range([0, config.amplitude, 0]) .domain([0, 50, 100]); var waveheight = (config.h / 2) * waveheightscale(fillpercent * 100); var wavelength = config.w / config.countperwidth; var waveclipcount = 1 + config.countperwidth; var waveclipwidth = wavelength * waveclipcount; // data building clip wave area. var data = []; (var = 0; <= 40 * waveclipcount; i++) { data.push({ x: / (40 * waveclipcount), y: (i / (40)) }); } // scales controlling size of clipping path. var wavescalex = d3.scale.linear().range([0, waveclipwidth]).domain([0, 1]); var wavescaley = d3.scale.linear().range([0, waveheight]).domain([0, 1]); // scales controlling position of clipping path. var waverisescale = d3.scale.linear() // clipping area size height of fill circle + wave height, position clip wave // such overlap fill circle @ when @ 0%, , totally cover fill // circle @ 100%. .range([(config.h + waveheight), (waveheight)]) .domain([0, 1]); var waveanimatescale = d3.scale.linear() .range([0, waveclipwidth - config.w]) // push clip area 1 full wave snap back. .domain([0, 1]); // center gauge within parent svg. var gaugegroup = gauge.append("g") .attr("class", "gaugegroup") .attr("transform", "translate(0,0)"); var randomid = math.floor(math.random() * 26) + date.now(); // clipping wave area. var cliparea = d3.svg.area() .x(function(d) { return wavescalex(d.x); }) .y0(function(d) { return wavescaley(math.sin(math.pi * 2 * config.offset * -1 + math.pi * 2 * (1 - config.countperwidth) + d.y * 2 * math.pi)); }) .y1(function(d) { return (config.h + waveheight); }); var wavegroup = gaugegroup.append("defs") .append("clippath") .attr("id", "clipwave" + randomid); var wave = wavegroup.append("path") .datum(data) .attr("d", cliparea) .attr("t", 0); // inner circle clipping wave attached. var fillgroup = gaugegroup.append("g") .attr("clip-path", "url(#clipwave" + randomid + ")"); fillgroup.append("rect") .attr("x", 0) .attr("y", 0) .attr("width", config.w) .attr("height", config.h) .style("fill", config.colorbefore) .transition() .duration(config.colortransition) .style("fill", config.colorafter); // make wave rise. wave , wavegroup separate horizontal , vertical movement can controlled independently. var wavegroupxposition = config.w - waveclipwidth; if (config.rise) { wavegroup.attr('transform', 'translate(' + wavegroupxposition + ',' + waverisescale(0) + ')') .transition() .duration(config.risetime) .attr('transform', 'translate(' + wavegroupxposition + ',' + waverisescale(fillpercent) + ')') .each("start", function() { wave.attr('transform', 'translate(1,0)'); }); // transform necessary clip wave positioned correctly when waverise=true , waveanimate=false. wave not position correctly without this, it's not clear why necessary. } else { wavegroup.attr('transform', 'translate(' + wavegroupxposition + ',' + waverisescale(fillpercent) + ')'); } animatewave(); function animatewave() { wave.attr('transform', 'translate(' + waveanimatescale(wave.attr('t')) + ',0)'); wave.transition() .duration(config.animatetime * (1 - wave.attr('t'))) .ease('linear') .attr('transform', 'translate(' + waveanimatescale(1) + ',0)') .attr('t', 1) .each('end', function() { wave.attr('t', 0); animatewave(config.animatetime); }); } }
Comments
Post a Comment