我创建了一个c3散点图,根据数据生成不同大小的点。如果图形的最左侧或最右侧附近的点相对较大,则它不会被包含在图形中,并且该点的一部分被切断。如果我添加静态填充,图表不会针对不同的情况进行适当缩放,并且有时会有太多或太少的填充。有没有办法通过动态生成填充来包含图中的点?
代码:
function getChart(gridData) {
var colors = ['#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#4392c3', '#2166ac'];
var columns = [];
var mySize = {};
var mySizeArray = [];
var myXs = {};
var myNames = [];
var myPointColors;
myPointColors = {};
var pointSize;
var newData = extractPointsFromGrid(gridData);
pointSize = function (sizeVal, sizes) {
var Incidence = sizeVal;
var MIN_incidence = d3.min(sizes);
var MAX_incidence = d3.max(sizes);
var qtl3 = d3.mean(sizes);
//noinspection OverlyComplexArithmeticExpressionJS
var s = ((Incidence - MIN_incidence) * (50 - 10)) / (MAX_incidence - MIN_incidence) + 3;
return (s + Math.floor(qtl3) > 3) ? s + Math.floor(qtl3) : 3;
};
var bubbleSizes = function (sizes) {
var _sizes = typeof sizes === 'object' ? sizes : [];
var len = (typeof _sizes === 'object') ? sizes.length : 0;
var sizesArray = _.pluck(_sizes, 'iCumulative');
var reacsArray = _.pluck(_sizes, 'reac');
var newSizes = [];
_sizes.forEach(function (size) {
var newSize = pointSize(Math.abs(size.iCumulative), sizesArray);
newSizes.push({'reac': size.reac, 'size': newSize});
});
window.sizes = newSizes;
return newSizes;
};
var myNameIndex = [];
var myPointSizes = [];
var i = 0;
var myColors = bubbleColors.reverse();
var myPts = bubbleSizes(newData);
var dynamicPadding = addDynamicPadding(myPts, newData);
newData.forEach(function (d) {
var name = d.reac;
var myRor = [d.reac];
var myPs = [d.reac + "_Primary Suspect"];
myRor.push(d.ROR);
myPs.push(d.PS);
myNames.push(d.reac);
myNameIndex[i] = d.reac;
myPointColors[d.reac] = myColors[i];
columns.push(myRor);
columns.push(myPs);
myXs[myRor[0]] = myPs[0];
mySize[d.reac] = d.iCumulative;
myNameIndex[d.reac] = d.PS;
myPointSizes.push = {'reac': d.reac, 'size': d.iCumulative};
i++;
});
var chart = c3.generate({
bindto: '#rxsignal-chart-bubble',
size: {
height: 200
},
data: {
xs: myXs,
columns: columns,
type: 'scatter',
colors: myPointColors
},
axis: {
x: {
label: 'Primary Suspect Cases',
tick: {
fit: false
},
// padding: {top: 200, left: 0, right: 0, bottom: 0}
},
y: {
label: 'ROR',
tick: {
fit: false,
format: function (d) {
return (d < 0) ? '' : d;
}
},
// padding: {top: 5, left: 5, right: 100, bottom: 5}
}
},
point: {
r: function (d) {
pointSize = _.where(myPts, {reac: d.id})[0];
return pointSize.size;
},
focus: {
expand: {
enabled: false,
r: function (d) {
return d.r;
}
}
}
},
tooltip: {
format: {
title: function (d) {
return false;
},
name: function (name) {
return name;
},
value: function (value, ratio, id, size, x) {
var numFormat = d3.format(',');
var decFormat = d3.format('.');
var pctgFormat = d3.format('.4p');
return '<tr colspan="2"><td>Primary Suspect Cases</td><td>' + numFormat(myNameIndex[id]) + '</td></tr>' + '<tr><td>ROR</td><td>' + numFormat(value) + '</td></tr>';
}
}
}
});
var getPaddingChange = function (chart) {
var change = {
top: 0,
left: 0,
right: 0,
bottom: 0
};
var m = chart.internal.main.node().parentNode.getBoundingClientRect();
// the chart area is shifted by this transform - so we need to adjust the point coordinates by this amount
var t = d3.transform(chart.internal.main.attr("transform")).translate;
// loop through each point
chart.internal.main.selectAll('.' + c3.chart.internal.fn.CLASS.circle).each(function () {
var c = this.getBBox();
// left clipping
if (c.x < -t[0])
change.left = Math.max(change.left, -(c.x + t[0]));
// right clipping
if ((c.x + c.width) > (m.width - t[0]))
change.right = Math.max(change.right, (c.x + c.width) - (m.width - t[0]));
// top clipping
if (c.y < -t[1])
change.top = Math.max(change.top, -(c.y + t[1]));
// bottom clipping
if ((c.y + c.height) > (m.height - t[1]))
change.bottom = Math.max(change.bottom, (c.y + c.height) - (m.height - t[1]));
})
return change;
}
var change = getPaddingChange(chart);
chart.internal.config.padding_top = chart.internal.getCurrentPaddingTop() + change.top;
chart.internal.config.padding_bottom = chart.internal.getCurrentPaddingBottom() + change.bottom;
chart.internal.config.padding_left = chart.internal.getCurrentPaddingLeft() + change.left;
chart.internal.config.padding_right = chart.internal.getCurrentPaddingRight() + change.right;
// force a redraw
chart.flush();
// remove clip path
chart.internal.main.select('.' + c3.chart.internal.fn.CLASS.chart).attr('clip-path', null);
}
答案 0 :(得分:3)
调整图表填充(而不是轴填充)会更简单。这也可以确保一旦删除clippath,你的圈子就不会被剪裁
这是主要功能,可根据圆圈的剪裁程度计算(如果有的话) - 即它可以为您提供添加到填充所需的额外调整
var getPaddingChange = function (chart) {
var change = {
top: 0,
left: 0,
right: 0,
bottom: 0
};
var m = chart.internal.main.node().parentNode.getBoundingClientRect();
// the chart area is shifted by this transform - so we need to adjust the point coordinates by this amount
var t = d3.transform(chart.internal.main.attr("transform")).translate;
// loop through each point
chart.internal.main.selectAll('.' + c3.chart.internal.fn.CLASS.circle).each(function () {
var c = this.getBBox();
// left clipping
if (c.x < -t[0])
change.left = Math.max(change.left, -(c.x + t[0]));
// right clipping
if ((c.x + c.width) > (m.width - t[0]))
change.right = Math.max(change.right, (c.x + c.width) - (m.width - t[0]));
// top clipping
if (c.y < -t[1])
change.top = Math.max(change.top, -(c.y + t[1]));
// bottom clipping
if ((c.y + c.height) > (m.height - t[1]))
change.bottom = Math.max(change.bottom, (c.y + c.height) - (m.height - t[1]));
})
return change;
}
这就是它如何适应流程的其余部分 - chart
是你的C3图表对象
var change = getPaddingChange(chart);
chart.internal.config.padding_top = chart.internal.getCurrentPaddingTop() + change.top;
chart.internal.config.padding_bottom = chart.internal.getCurrentPaddingBottom() + change.bottom;
chart.internal.config.padding_left = chart.internal.getCurrentPaddingLeft() + change.left;
chart.internal.config.padding_right = chart.internal.getCurrentPaddingRight() + change.right;
// force a redraw
chart.flush();
// remove clip path
chart.internal.main.select('.' + c3.chart.internal.fn.CLASS.chart).attr('clip-path', null);
小提琴 - http://jsfiddle.net/b7ns8muv/
我删除了underscore.js函数调用。
以下是调整之前和之后的样子。请注意,从“之前”图表中取出clippath也可以更好地了解调整。