datavizstocklib
Version:
测试一下呗
880 lines (808 loc) • 34.8 kB
JavaScript
import * as d3 from "d3";
import { color } from "d3";
let config = {
/** 控件名 */
name: "DivergingBar",
/** svg 对象 */
svg: {},
/** 展示类型 Dynamic Fixed Custom */
scaleType: "Dynamic",
/** 数据 */
data: [],
/** 内部使用 */
jsonData: {},
/** 内部使用 当前展示的数据 */
currentData: [],
/** 表头名集合 */
columnName: [],
/** 图表默认高度 */
clientHeight: 500,
/** 图表默认宽度 */
clientWidth: 0,
/** 升序或降序 asc desc */
sort: "desc",
/** Y轴比例尺 */
yScale: {},
/** X轴比例尺 */
xScale: {},
/** 边距设置 上,右,下,左 */
margin: [60, 100, 60, 100],
/** colors */
colors: [],
/** 最大文字的字号 */
YfontSize: 25, //字号
/** 字体 */
fontfamilyBase: "SourceHanSansK-Regular-plotly,Helvetica Neue,PingFang SC,Microsoft YaHei,Helvetica,Hiragino Sans GB,Arial,sans-serif",
/** 文字颜色 */
rectTextColor: "#A3A3A3",
/** 条数 */
barNumber: 5,
/** 柱高度自适应 */
rectHeightFixed: false,
// 柱子高度
rectHeight: 100,
/** 柱高度和 柱间距的比例 */
rectRate: 5,
/** 内部使用 */
rectSpace: 0,
/** X轴坐标位置 bottom top */
xAxisPos: "top",
/** 动画时长 */
durationTime: 1000,
/** 最大值 */
maxValue: 0,
/** 延时播放 */
delay: 2000,
height: 35,
/** 内部使用 */
isRun: false,
replay: false,
showRanking: true,
/** 矩形圆角 */
rx: 2,
index: 0,
dataIndex: 0,
timeout: null,
rankingFontsize: 16,
xSicks: 5,
showThousands: true,
pointFormat: 'auto',
el: '_dataviz',
d3Ease:'',
// 是否填充渐变色
ifGradient: false,
// 是否填显示尖角
rectSharpCorner: false,
// 图片
useImages: true,
// 名称显示在左边,否则显示在柱子上
nameAtLeft: true,
centerWidth: 240,
valuePosition: 'in'
}
String.prototype.replaceAll = function (s1, s2) {
return this.replace(new RegExp(s1, "gm"), s2);
}
export class DivergingBar {
/** 构造器 */
constructor() {
let newconfig = JSON.parse(JSON.stringify(config));
Object.assign(this, newconfig)
}
/** 更新图表 */
update(obj) {
// this.arrayToJson();
// 复制新配置
Object.assign(this, obj)
}
addLegend() {
let that = this;
let colorName=new Set()
for (let i = 1; i < that.data.length; i++) {
colorName.add(that.data[i][0])
}
let colors=([...colorName]).map((d,i)=>{
return {name:d, color: this.colors[i]}
})
//清空原图例下所有数据
that.svg.select(".bcrlegend").selectAll("g").remove();
var binding = that.svg.select(".bcrlegend")
.selectAll("g")
.data(colors, function (d) { return d.name; });
binding.exit().transition().duration(that.durationTime).remove();
let width=that.clientWidth - this.margin[1] - this.margin[3];
let height=that.clientHeight - this.margin[0] - this.margin[2];
that.svg.select(".bcrlegend")
.attr('transform', 'translate(' + (width/2+this.margin[1]-80) + ',' + (that.margin[0] + 15 + height) + ' )')
let enterG = binding.enter().append("g");
let offset = 0
enterG.append("rect")
.attr("width", (that.legendFontSize - 2)).attr("height", (that.legendFontSize - 2))
.attr("rx", that.rx)
.attr('transform', function (d, i) {
let beforeOffset = offset
offset = parseInt(d.name.length * 5) + parseInt(beforeOffset) + 20 + that.legendFontSize * 4
return 'translate(' + beforeOffset + ',' + -(that.legendFontSize - 6) / 2 + ' )';
// return 'translate(' + i * 75 + ',' + 0 + ' )';
}).attr("fill", function (d, i) {
if (that.isTemplate && that.gradient) return 'url(#colorGradient)'
return d['color'];
});
let offsetText = 0
enterG.append("text").attr("font-size", that.legendFontSize)
.attr('fill', that.fontColor)
.attr('transform', function (d, i) {
let beforeOffset = offsetText || that.legendFontSize
offsetText = parseInt(d.name.length * 5) + parseInt(beforeOffset) + 20 + that.legendFontSize * 4
return 'translate(' + beforeOffset + ',' + that.legendFontSize/2 + ' )';
//return 'translate(' + (i * 75 + 12) + ',' + 10 + ' )';
}).text(function (d, i) {
return d.name;
})
}
/** 重新播放 */
replay() { }
/** 播放 */
play() { }
/** 暂停 */
pause() { }
/** 初始化 */
init(obj, callback) {
let that = this;
Object.assign(this, obj);
this.index = 1
let c = that.colors.concat()
for (let i = 0; i <= that.data.length; i = i + c.length) {
that.colors = that.colors.concat(c)
}
this.getEase();
that.arrayToJson();
that.svg = d3.select("#" + this.el).append("svg");
that.svg.append("g").attr("class", "bcrlegend");
if (this.showLegend && !this.isTemplate) {
this.addLegend();
} else {
this.svg.select(".bcrlegend").selectAll("g").remove();
}
//添加竖线
that.svg
.append("g")
.attr("class", "grid-left")
.style("color", "#A3A3A3")
.style("font-size", that.XfontSize)
//添加竖线
that.svg
.append("g")
.attr("class", "grid-right")
.style("color", "#A3A3A3")
.style("font-size", that.XfontSize)
if (that.clientWidth == 0) {
that.clientWidth = document.getElementById(this.el).clientWidth;
}
that.svg.attr("width", that.clientWidth).attr("height", that.clientHeight);
let {showDataRight, showDataLeft, showTime, colors} = that.getData();
let maxValue = d3.max(showDataRight.concat(showDataLeft),(d)=>{return +d.value})//that.max(currentData);
let minValue = d3.min(showDataRight.concat(showDataLeft),(d)=>{return +d.value});
let width = that.clientWidth - this.margin[1] - this.margin[3];
that.xScale = d3.scaleLinear()
.range([that.margin[3], width + that.margin[3]]) // 界面像素范围
.domain([minValue, maxValue]); //数据范围
//创建y轴比例尺
let chart = that.svg.append("g").attr("width", that.clientWidth).attr("height", that.clientHeight).append("g");
//生成y轴
chart.append("g").attr("id", "yyyy")
//生成x轴
chart.append("g").attr("id", "xxxx")
that.bar = that.svg.append("g");
that.svg.append("text").attr("class", "topText")
.attr("x", that.clientWidth * 0.9)
.attr("y", that.margin[0] - that.rectRate * 5-10)
.text('')
.attr("text-anchor", "end")
.attr("font-size", that.rankingFontsize)
.attr("fill", that.fontColor);
this.dataIndex = this.jsonData.length + 1
clearTimeout(this.timeout);
if (this.timeout != null) this.timeout.stop();
let colorGradient = that.svg.append("defs").append("linearGradient").attr('id', 'colorGradient').attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%")
colorGradient.append('stop').attr('id', 'stop1').attr('offset', '0%').attr('stop-color', that.colors[0])
colorGradient.append('stop').attr('id', 'stop2').attr('offset', '100%').attr('stop-color', that.colors[1])
let rectFilter = that.svg.append("defs").append("filter").attr('id', 'f1').attr('x', '0').attr('y', '0').attr('width', '200%').attr('height', '200%')
rectFilter.append('feOffset').attr('result', 'offOut').attr('in', 'SourceAlpha').attr('dx', '2').attr('dy', '2')
rectFilter.append('feGaussianBlur').attr('result', 'blurOut').attr('in', 'offOut').attr('stdDeviation', '10')
rectFilter.append('feBlend').attr('in', 'SourceGraphic').attr('in2', 'blurOut').attr('mode', 'normal')
let rectFilter2 = that.svg.append("defs").append("filter").attr('id', 'empty').attr('x', '0').attr('y', '0').attr('width', '200%').attr('height', '200%')
rectFilter2.append('feOffset').attr('result', 'offOut').attr('in', 'SourceAlpha').attr('dx', '0').attr('dy', '0')
rectFilter2.append('feGaussianBlur').attr('result', 'blurOut').attr('in', 'offOut').attr('stdDeviation', '0')
rectFilter2.append('feBlend').attr('in', 'SourceGraphic').attr('in2', 'blurOut').attr('mode', 'normal')
that.updateChart(callback);
// that.updateXAxis();
}
getEase(){
this.d3Ease=d3;
this.animateType.split(".").forEach(item=>{
if(item.indexOf("(")>-1){
let arr=item.split("(")
this.d3Ease=this.d3Ease[arr[0]](arr[1].replace(")",""))
}else{
this.d3Ease=this.d3Ease[item]
}
})
}
updataImages() {
let that = this;
for (var i = 0; i < that.jsonData.length; i++) {
that.jsonData[i]["image"] = that.dynamicImages[i]
}
}
/**
* 页面渲染
* @param {*} year
*/
updateChart(callback) {
if (this.showLegend && !this.isTemplate) {
this.addLegend();
} else {
this.svg.select(".bcrlegend").selectAll("g").remove();
}
let that = this;
this.arrayToJson()
this.getEase();
let { showDataRight, showDataLeft, showTime, colors } = that.getData();
// that.clientWidth = document.getElementById(this.el).clientWidth;
that.svg.attr("width", that.clientWidth).attr("height", that.clientHeight);
d3.select('#stop1').attr('stop-color', that.colors[0]);
d3.select('#stop2').attr('stop-color', that.colors[1]);
let uirange = [];
let clientHeight = (this.showLegend && !this.isTemplate) ? that.clientHeight-that.legendFontSize*2 : that.clientHeight
uirange.push(clientHeight - that.margin[2]);
uirange.push(that.margin[0]);
that.yScale = d3.scaleBand()
.paddingInner(that.rectRate)
.paddingOuter(that.rectRate)
.range(uirange) // 界面像素范围
.domain(d3.range(that.barNumber)); //数据范围
// 设定最大值
that.height = Math.min(that.yScale.bandwidth(), 60)//(that.clientHeight - that.margin[0] - that.margin[2]) * 0.95 / that.barNumber * that.rectRate
that.rectHeight= that.height
that.yScale.domain(d3.range(that.barNumber)); //数据范围
let imageHeight = Math.max(that.rectHeight, 30)
let width = that.clientWidth - this.margin[1] - this.margin[3];
let eachWidth = (width - that.centerWidth)/2
// let rightMargin3 = (width - that.centerWidth)/2 + this.margin[1] +
that.xScaleRight = d3.scaleLinear()
.range([that.margin[3] + eachWidth + that.centerWidth, width + that.margin[3]]); // 界面像素范围
that.xScaleLeft = d3.scaleLinear()
.range([that.margin[3] + eachWidth, that.margin[3]]); // 界面像素范围
let maxValue = d3.max(showDataRight.concat(showDataLeft), (d) => +d.value);// 获取最大值
let minValue = 0;
that.xScaleRight.domain([minValue, maxValue]); //数据范围
that.xScaleLeft.domain([minValue, maxValue]); //数据范围
let gridHeight = clientHeight - that.margin[0] - that.margin[2];
this.drawChart(showDataRight, that.xScaleRight, that.yScale, colors, minValue, imageHeight, gridHeight, 'right')
this.drawChart(showDataLeft, that.xScaleLeft, that.yScale, colors, minValue, imageHeight, gridHeight, 'left')
that.svg.select('.topText')
.attr('visibility', that.showRanking ? 'visible' : 'hidden')
.attr("x", that.svg.attr("width") * 0.9)
.attr("y", that.margin[0] - that.rectRate * 5-10)
.attr("font-size", that.rankingFontsize)
.text(function (d, i) {
return showTime
})
.attr("fill", that.fontColor)
this.timeout = d3.timeout(function () {
if (that.index > (that.columnName.length - 2)) {
callback(that.index, true)
that.index = 0
} else {
if (that.isPlay) {
callback(that.index, false)
that.updateChart(callback);
that.index++;
that.dataIndex--
}
}
}, that.durationTime);
}
// 绘制图表
drawChart(showData,xScale,yScale,colors, minValue,imageHeight, gridHeight, type){
// 左右两边的偏移量
let offset = type=="left"?10:-10
let that = this
// bar的偏移量
let barYOffset = "bottom" == that.xAxisPos ? 0 : 30
if (!that.showAxisX) that.xSicks = 0
let gridscale = d3["bottom" == that.xAxisPos ? "axisBottom" : "axisTop"]()
.tickPadding(12)
.scale(xScale)
.ticks(that.xSicks)
.tickSize(-gridHeight, 0, 0)
.tickFormat(d => {
if (d < 0) {
return ""
}
if (!that.showAxisX) return ""
return that.format(d)
})
that.svg.select(".grid-"+type)
.attr('transform', ()=>{
if("bottom" == that.xAxisPos){
return 'translate(' + 0 + ',' + (that.clientHeight - that.margin[2] ) + ' )'
}else{
return 'translate(' + 0 + ',' + ( that.margin[0] + barYOffset ) + ' )'
}
})
.style("font-size", that.XfontSize)
.transition()
.duration(that.durationTime)
.call(gridscale)
.ease(that.d3Ease)
that.svg.select(".grid-"+type).selectAll("Text")
.attr('transform', 'translate(0,10)')
.attr("dy",function(){
return 0;
})
.style("font-size", that.XfontSize)
.attr("fill", that.fontColor)
.attr("fill-opacity", 1);
that.svg.select(".grid-"+type).selectAll("line").attr("opacity", 0.4);
that.svg.select(".grid-"+type).select("path").remove();
var binding = that.bar.selectAll('.g-'+type)
.data(showData, d=>d.name);
binding.exit()
.transition()
.duration(that.durationTime)
.attr("transform", function (d, i) {
return "translate(" + xScale(minValue) + "," + (yScale(0) + that.height + barYOffset) + ")";
})
.ease(that.d3Ease)
.attr("opacity",0.0001)
.remove();
//补充新的元素
let enterG = binding.enter()
.append("g")
.attr("class","g-"+type)
.attr("opacity", 1);
// 新元素初始化
enterG.attr("opacity",0.0001)
.attr("transform", function (d, i, data) {
return "translate(" + xScale(minValue) + "," + (yScale(0) + that.height + barYOffset) + ")";
})
.transition()
.duration(that.durationTime)
.attr("transform", function (d, i) {
return "translate(" + xScale(minValue) + "," + (yScale(that.barNumber-1-i) + barYOffset) + ")";
})
.attr("opacity", 1)
.ease(that.d3Ease);
// 添加path替换原始的rect,提升代码的通用性和可配置性
enterG.append("rect")
.attr("class","rect-path")
.transition()
.ease(that.d3Ease)
.duration(that.durationTime)
.attr("x",(d)=>{
if(type=="right"){
return 0
}else{
return -Math.abs(xScale(d.value)-xScale(0))
}
})
.attr("y",d=>{
return 0
})
.attr("height",d=>{
return that.height
})
.attr("width",d=>{
return Math.abs(xScale(d.value)-xScale(0))
})
.attr("rx",that.rx)
.attr("fill", function (d, i) {
if (that.ifGradient) return 'url(#colorGradient)'
return colors[d.group];
})
.attr("stroke", "#fff")
.attr("stroke-width", function () {
if (that.templateType == 'template0') return '2px'
return '0px'
})
.attr('filter', function () {
if (that.templateType == 'template1'||that.templateType=="template_csl") return "url(#f1)"
return 'url(#empty)'
});
// 名称文字
enterG.append("text")
.text(function (d, i) {return '';})
.attr("font-size", that.valuePosition==="out"? that.YfontSize+4:that.YfontSize)
.attr("font-family", that.fontfamilyBase)
.attr("fill", that.fontColor)
.attr("class", 'yText')
.attr('font-family', 'DINPro')
.attr("text-anchor", d=>{
if(type=='left') return "end"
else return 'start'
})
.transition()
.duration(that.durationTime)
.ease(that.d3Ease)
.tween("text",function(d){
let self = this
let numLabel=""
if(that.valuePosition==="out"){
if(!that.showLabel){
numLabel=""
}else{
if (!that.interpolate){
numLabel=that.format(d.value)
d3.select(self).text( numLabel);
}else{
let maxLength = that.countDecimals(d.value)
let interNum = d3.interpolateNumber(0, Number(d.value))
return function (t){
numLabel = that.format(Number(interNum(t)).toFixed(maxLength));
d3.select(self).text( numLabel)
}
}
}
}else{
d3.select(self).text(d.name);
}
})
.attrTween("transform", function (d, i) {
let width = xScale(d.value) - xScale(minValue)
let inter=d3.interpolateNumber(0,width)
return function(t){
return "translate("+ (inter(t)-offset) +"," + (that.height / 2 + 0.8 * that.YfontSize/2) + ")";
}
});
binding.select('.yText')
.attr("font-size", that.valuePosition==="out"? that.YfontSize+4:that.YfontSize)
.attr("opacity",function (d, i) {
return 1;
})
.attr('font-family', 'DINPro')
.transition()
.duration(that.durationTime)
.ease(that.d3Ease)
.attr("transform", function (d, i) {
let width = xScale(d.value) - xScale(minValue)
return "translate("+ (width-offset) +"," + (that.height / 2 + 0.8 * that.YfontSize/2) + ")";
})
.tween("text",function(d){
let self = this
let numLabel=""
if(that.valuePosition==="out"){
if(!that.showLabel){
numLabel=""
}else{
if (!that.interpolate){
numLabel=that.format(d.value)
d3.select(self).text( numLabel);
}else{
let maxLength = that.countDecimals(d.value)
let interNum = d3.interpolateNumber(0, Number(d.value))
return function (t){
numLabel = that.format(Number(interNum(t)).toFixed(maxLength));
d3.select(self).text( numLabel)
}
}
}
}else{
d3.select(self).text(d.name);
}
})
.attr("fill", that.fontColor)
// 添加柱子的文字——数字
enterG.append("text")
.attr("class", "tips")
.attr("stroke", "#fff")
.attr("stroke-width", function () {
if (that.templateType == 'template0') return '0.5px'
return '0px'
})
.attr("transform", function (d, i) {
let posY= that.height / 2 + 0.8 * that.YfontSize/2
return "translate(" + 0 + "," + posY+")";
})
.transition().duration(that.durationTime)
.attr("font-size", that.valuePosition==="in"?that.YfontSize + 4:that.YfontSize)
.attr("transform", function (d, i) {
let posY= that.height / 2 + 0.8 * that.YfontSize/2
return "translate(" + offset + "," + posY+")";
})
.attr("text-anchor", ()=>{
return type=="left"?"start":"end"
})
.attr("fill", function (d) {
if (that.templateType == 'template1' && that.gradient) return that.colors[1]
if (that.templateType == 'template0') return d['_inner_color'];
return that.fontColor
})
.attr('font-family', 'DINPro')
.tween("text", function (d, i) {
let self = this
if(that.valuePosition==="in"){
if(!that.showLabel){
d3.select(self).text("")
}else{
if (!that.interpolate){
d3.select(self).text(that.format(d.value))
}else{
let maxLength = that.countDecimals(d.value)
let interNum = d3.interpolateNumber(0, Number(d.value))
return function (t){
d3.select(self).text(that.format(Number(interNum(t)).toFixed(maxLength)))
}
}
}
}else{
d3.select(self).text(d.name);
}
})
.on("end",function(d){
d3.select(this).attr("preValue",d.value)
})
.ease(that.d3Ease);
binding.select(".tips")
.transition()
.duration(that.durationTime)
.ease(that.d3Ease)
.attr("transform", function (d, i) {
let posY= that.height / 2 + 0.8 * that.YfontSize/2
return "translate(" + offset + "," + posY + ")";
})
.attr("fill", function (d) {
return that.fontColor
})
.attr("font-size", that.valuePosition==="in"?that.YfontSize + 4:that.YfontSize)
.tween("text", function (d, i) {
let self = this
if(that.valuePosition==="in"){
if(!that.showLabel){
d3.select(self).text("")
}else{
if (!that.interpolate){
d3.select(self).text(that.format(d.value))
}else{
let preNum = d3.select(this).attr("preValue")
let maxLength = Math.max(that.countDecimals(preNum),that.countDecimals(d.value))
let interNum = d3.interpolateNumber(Number(preNum), Number(d.value))
return function (t){
d3.select(self).text(that.format(Number(interNum(t).toFixed(maxLength))))
}
}
}
}else{
d3.select(self).text(d.name);
}
})
.on("end",function(d){
d3.select(this).attr("preValue",d.value)
})
binding.select(".rect-path")
.transition()
.duration(that.durationTime)
.attr("x",(d)=>{
if(type=="right"){
return 0
}else{
return -Math.abs(xScale(d.value)-xScale(0))
}
})
.attr("y",d=>{
return 0
})
.attr("height",d=>{
return that.height
})
.attr("width",d=>{
return Math.abs(xScale(d.value)-xScale(0))
})
.attr("rx",that.rx)
.attr('filter', function () {
if (that.templateType == 'template1'||that.templateType=="template_csl") return "url(#f1)"
return 'url(#empty)'
})
.attr("fill", function (d, i) {
if (that.ifGradient) return 'url(#colorGradient)'
return colors[d.group];
})
.ease(that.d3Ease);
binding.transition()
.duration(that.durationTime)
.attr("transform", function (d, i) {
return "translate(" + xScale(minValue) + "," + (yScale(that.barNumber-1-i) + barYOffset) + ")";
})
.ease(that.d3Ease);
that.svg.selectAll("g-"+type).attr('opacity', '1')
// 添加图表icon
if (that.useImages ) {
let imageOffset = type == "left" ? 10 : 10-(imageHeight * 3 / 2 - 5)
enterG.append('image')
.attr("class", "image")
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("width", function (d, i) {
if (that.dynamicImages[type=="left"?0:1] && Math.abs(xScale(d.value)-xScale(0)) > imageHeight * 3 / 2 - 5) {
return imageHeight * 3 / 2 - 5
} else {
return 0
}
})
.attr("height", function (d, i) {
return imageHeight
})
.attr("x", -10)
.attr("y", function (d, i) {
return 0//(that.rectHeight + (8 * that.YfontSize / that.rectHeight + 1.5 * that.rectHeight / that.barNumber)) - that.rectHeight - that.rectHeight/2
//return that.rectHeight + i * (that.rectHeight + that.rectSpace);
})
.transition()
.duration(that.durationTime)
.ease(that.d3Ease)
.attr("transform", function (d, i) {
return "translate(" + (xScale(d.value) - xScale(minValue) + imageOffset) + "," + (that.rectHeight-imageHeight)/2 + ")";
})
.attr("xlink:href", function (d, i) {
let img = that.dynamicImages[type=="left"?0:1]//d["image"]
if (img) return img
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAABVCAYAAADNCyPqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAADGSURBVHhe7dAxAQAwDMCg+ffctSr4cmCA92c2TsFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjB1OwBeFHfxoh6bUcAAAAASUVORK5CYII="
});
binding.select(".image")
.attr("width", function (d, i) {
if ( that.dynamicImages[type=="left"?0:1] && Math.abs(xScale(d.value)-xScale(0)) > imageHeight * 3 / 2 - 5) {
return imageHeight * 3 / 2 - 5
} else {
return 0
}
})
.transition().duration(that.durationTime)
.attr("height", function (d, i) {
return imageHeight
})
.attr("x", -10)
.attr("y", function (d, i) {
return 0//(that.rectHeight + (8 * that.YfontSize / that.rectHeight + 1.5 * that.rectHeight / that.barNumber)) - that.rectHeight - that.rectHeight/2
}).attr("text-anchor", "start")
.attr("transform", function (d, i) {
return "translate(" + (xScale(d.value) - xScale(minValue) + imageOffset) + "," + (that.rectHeight - imageHeight)/2 + ")";
}).ease(that.d3Ease);
}
}
countDecimals (value) {
if(!value){
return 0
}
if(Math.floor(value) === Number(value)) return 0;
if (!String(value).split(".")[1]){
return 0
}
return String(value).split(".")[1].length || 0;
}
updateObj(obj, callback) {
clearTimeout(this.timeout);
this.timeout.stop();
Object.assign(this, obj)
if (this.replay) {
this.dataIndex = this.jsonData.length + 1
this.index = 0
d3.select("#" + this.el).html('')
this.init(obj, callback)
} else {
let c = this.colors.concat()
for (let i = 0; i <= this.data.length; i = i + c.length) {
this.colors = this.colors.concat(c)
}
this.updateChart(callback)
}
}
destroy() {
clearTimeout(this.timeout);
if (this.timeout != null) this.timeout.stop();
Object.assign(this, null)
}
getData() {
let that=this
// 获取组
let groups=that.jsonData.map(d=>{
return d[that.columnName[0]]
}).filter((value,index,data)=>{
return index==data.indexOf(value)
})
// 获取颜色
let colors = {}
groups.forEach((d, i)=>{
colors[d]=that.colors[i]
})
// 获取当前时间
let showTimeIndex=that.index+1>that.columnName.length-1 ? that.columnName.length-1:that.index+1
let showTime = that.columnName[showTimeIndex]
// 获取当前数据
let showDataRight=that.jsonData.map(d=>{
return {
name: d[that.columnName[1]],
value: +d[showTime],
group: d[that.columnName[0]]
}
})
.filter(d=>d.group==groups[1])
.sort((a,b)=>{
return -(+a.value) + (+b.value)
})
.slice(0,that.barNumber)
let showDataLeft=that.jsonData.map(d=>{
return {
name: d[that.columnName[1]],
value: +d[showTime],
group: d[that.columnName[0]]
}
})
.filter(d=>d.group==groups[0])
.sort((a,b)=>{
return -(+a.value) + (+b.value)
})
.slice(0,that.barNumber)
return {showDataRight, showDataLeft, showTime, colors}
}
/** 千分位格式化 */
format(num) {
if (this.pointFormat == 0) {
num = parseInt(num)
} else if (this.pointFormat == 1) {
num = parseFloat(num).toFixed(1)
} else if (this.pointFormat == 2) {
num = parseFloat(num).toFixed(2)
} else {
num = Number(num)
}
let result = '';
if (this.showThousands) {
num = (num || 0).toString();
let a = num.split('.')[0] || num
let b = num.split('.')[1] || ""
while (a.length > 3) {
result = ',' + a.slice(-3) + result;
a = a.slice(0, a.length - 3);
}
if (a) { result = a + result; }
if (b) { result = result + "." + b }
} else {
result = num
}
if (this.showPercent) result = result + '%'
return result
}
arrayToJson() { //添加配色
let that = this;
that.data = that.removeNull(that.data)
that.columnName = that.data[0];
let json = [];
for (let i = 1; i < that.data.length; i++) {
let res = {};
for (let j = 0; j < that.columnName.length; j++) {
res[that.columnName[j]] = that.data[i][j];
}
// let cIndex = i % that.colors.length;
//res['_inner_color'] = that.colors[i-1];
json.push(res);
}
that.jsonData = json;
if (that.useImages) this.updataImages();
// that.sortJsonData();
}
removeNull(data) {
let array = []
for (let i = 0; i < data.length; i++) {
let a = []
for (let j = 0; j < data[i].length; j++) {
if (data[i][j] != null && data[i][j] != "" && data[i][j] != " ") {
data[i][j] = (data[i][j] + '').replace(/,/g, '')
a.push(data[i][j])
}
}
if (a.length > 0) array.push(a)
}
return array
}
}
export default DivergingBar;