d3.js化工管条形图
Posted
技术标签:
【中文标题】d3.js化工管条形图【英文标题】:d3.js chemical tube bar chart 【发布时间】:2017-09-10 23:23:54 【问题描述】:我对创建这种液体条形图很感兴趣。如图所示,指针/虚线标记拉到一边。
4 月 22 日 - 处理动态数据的最新代码 http://jsfiddle.net/NYEaX/1855/
最新条形图代码 http://jsfiddle.net/NYEaX/1827/
最新清理的水波代码 http://jsfiddle.net/Qh9X5/10331/
//我想去掉这个水波代码 http://jsfiddle.net/Qh9X5/10091/
//进度图 http://jsfiddle.net/NYEaX/1740/
此条形图的最新基本代码。 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
【问题讨论】:
我已经添加了标签 - jsfiddle.net/NYEaX/1825 --添加了虚线-但努力使垂直线匹配--jsfiddle.net/NYEaX/1826 设法解决了第二行 - 热衷于合并水效果 - 一种简化算法以实现集成的方法? jsfiddle.net/NYEaX/1827——水代码——jsfiddle.net/Qh9X5/10091 --我已经开始剥离这个波形代码了--jsfiddle.net/Qh9X5/10290 老兄,说真的,所有这些小提琴都没有帮助!您需要将所有这些外部信息浓缩到您的问题中,并明确说明您在问什么。 【参考方案1】:我已将这两个图表合并在一起 - 但如果水代码是单独的 svg 则正确翻译 - 最好清理/审查此代码。还要确保指针/标签调整/适应更多/更少的数据集。
最新的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, // The wave height as a percentage of the radius of the wave circle.
countPerWidth: 1, // The number of full waves per width of the wave circle.
riseTime: 1000, // The amount of time in milliseconds for the wave to rise from 0 to it's final height.
animateTime: 1000, // The amount of time in milliseconds for a full wave to enter the wave circle.
rise: true, // Control if the wave should rise from 0 to it's full height, or start at it's full height.
colorTransition: 1000,
colorBefore: value.startcolor, // The color before of the fill wave.
colorAfter: value.endcolor, // The color after of the fill wave.
offset: 0 // The amount to initially offset the wave. 0 = no offset. 1 = offset of one 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 a line
.style("stroke-dasharray", ("3, 3"))
.style("stroke", "black")// colour the line
.attr("x1", function(d, i)
return barWidth-(30 * (i+1));
)//x pos of the 1st end of the line
.attr("y1", function(d, i)
return 20 * i;
)//y pos of the 1st end of the line
.attr("x2", function(d, i)
return barWidth;
)//x pos of the 2nd end of the line
.attr("y2", function(d, i)
return 20 * i;
);//y pos of the 2nd end of the line
var lineHeights = 100;
lines.enter()
.append("line")// attach a line
.style("stroke-dasharray", ("3, 3"))
.style("stroke", "black")// colour the line
.attr("x1", function(d, i)
return 30 * i;
)//x pos of the 1st end of the line
.attr("y1", function(d, i)
return lineHeights - (20 * i);
)//y pos of the 1st end of the line
.attr("x2", function(d, i)
return 30 * i;
)//x pos of the 2nd end of the line
.attr("y2", function(d, i)
return -15;
);//y pos of the 2nd end of the 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 for building the clip wave area.
var data = [];
for (var i = 0; i <= 40 * waveClipCount; i++)
data.push(
x: i / (40 * waveClipCount),
y: (i / (40))
);
// Scales for controlling the size of the 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 for controlling the position of the clipping path.
var waveRiseScale = d3.scale.linear()
// The clipping area size is the height of the fill circle + the wave height, so we position the clip wave
// such that the it will overlap the fill circle at all when at 0%, and will totally cover the fill
// circle at 100%.
.range([(config.h + waveHeight), (waveHeight)])
.domain([0, 1]);
var waveAnimateScale = d3.scale.linear()
.range([0, waveClipWidth - config.w]) // Push the clip area one full wave then snap back.
.domain([0, 1]);
// Center the gauge within the parent SVG.
var gaugeGroup = gauge.append("g")
.attr("class", "gaugeGroup")
.attr("transform", "translate(0,0)");
var randomId = Math.floor(Math.random() * 26) + Date.now();
// The 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);
// The inner circle with the 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 the wave rise. wave and waveGroup are separate so that horizontal and vertical movement can be 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)');
); // This transform is necessary to get the clip wave positioned correctly when waveRise=true and waveAnimate=false. The wave will not position correctly without this, but it's not clear why this is actually 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);
);
【讨论】:
我已经尝试整理图表并提供上面的值标签 - 热衷于清理此图表 - 使其更多地用于处理动态/不同的数据集 - 这也是最好的方法为每个条创建背景 -- jsfiddle.net/NYEaX/1842 jsfiddle.net/NYEaX/1855 - 动态修复标签,使其贴紧到底部 这是一个与此图表相关的问题——***.com/questions/43507667/…以上是关于d3.js化工管条形图的主要内容,如果未能解决你的问题,请参考以下文章