UNPKG

datavizstocklib

Version:

测试一下呗

1,161 lines (1,070 loc) 42.6 kB
import * as d3 from "d3"; import { selectAll } from "d3"; let config = { /** * 控件名 */ name: "BarChartRace", /** * svg 对象 */ svg: {}, /** * 展示类型 Dynamic Fixed Custom */ scaleType: "Dynamic", /** * 数据 */ data: [], /** * 内部使用 */ jsonData: {}, /** * 内部使用 当前展示的数据 */ currentData: [], /** * 表头名集合 */ columnName: [], /** * 表头名集合 内部使用 */ columnInnerName: [], /** * 表头名索引 */ columnNameIndex: 2, /** * 图表默认高度 */ clientHeight: 500, /** * 图表默认宽度 */ clientWidth: 0, /** * 升序或降序 asc desc */ sort: "desc", /** * Y轴比例尺 */ yScale: {}, /** * X轴比例尺 */ xScale: {}, /** * 边距设置 上,右,下,左 */ margin: [60, 100, 60, 100], /** * colors */ colors: ["#5E4FA2", "#3288BD", "#66C2A5", "#ABDDA4", "#E6F598", "#FFFFBF", "#FEE08B", "#FDAE61", "#F46D43", "#D53E4F", "#9E0142"], /** * 内部使用 */ colorMap: null, /** * 按数据中第二列 数据分类来进行数据划分 true false */ colorsCateory: true, /** * 分类时是否展示图例 */ showLegend: true, /** * 最大文字的字号 */ fontsize: 50, //字号 /** * 字体类型 */ fontFamily: 'regular', //字体类型 /** * 字体 */ fontfamilyBase: "SourceHanSansK-Regular-plotly,Helvetica Neue,PingFang SC,Microsoft YaHei,Helvetica,Hiragino Sans GB,Arial,sans-serif", /** * 文字颜色 */ rectTextColor: "#A3A3A3", /** * 条数 */ barNumber: 5, /** * 柱高度自适应 */ rectHeightFixed: true, /** * 条高度 只有rectHeightFixed 为false 该值生效 */ rectHeight: 100, /** * 柱高度和 柱间距的比例 */ rectRate: 0.6, /** * 内部使用 */ rectSpace: 0, /** * X轴坐标位置 bottom top */ xAxisPos: "top", /** * 动画时长 */ durationTime: 1000, /** * 最大值 */ maxValue: 0, /** * 延时播放 */ delay: 2000, /** * 展示右下角年份 */ showYear: true, /** * 内部使用 */ isRun: false, /** * 左侧文字大小 */ YfontSize: 16, /** * 图例文字大小 */ legendFontSize: 12, //圆角 rx: 2, showThousands: true, pointFormat: 'auto', useImages: true, ticksNum: 5, animateType: 'easeLinear', d3Ease: '', terminal: '', el: '_dataviz' } String.prototype.replaceAll = function (s1, s2) { return this.replace(new RegExp(s1, "gm"), s2); } export class BarChartRace { /** * 构造器 */ constructor() { let newconfig = JSON.parse(JSON.stringify(config)); Object.assign(this, newconfig); } /** * 更新图表 * @param {JSON} obj */ update(obj) { // console.log("执行UPDATE"); this.clearAllTimeout(); // 复制新配置 Object.assign(this, obj) let that = this; this.getEase(); // 更新数据格式 this.arrayToJson(); that.bar.transition().duration(that.durationTime) .attr('transform', `translate(${this.margin[3]}, ${this.margin[0]})`).ease(this.d3Ease); if (!that.isRun) { //非运行状态 渲染最后一帧 let year = that.columnInnerName[that.columnName.length - 1]; that.columnNameIndex = that.columnName.length - 1; that.updateChart(year); } if (!that.showYear) { that.svg.select(".year").attr("font-size", "0") .attr("font-size", that.fontsize) .attr("fill", that.rectTextColor) } else { that.svg.select(".year").attr("font-size", that.fontsize) .attr("font-size", that.fontsize) .attr("fill", that.rectTextColor) } if (that.templateType == 'template_virus') { that.svg.select(".total") .text(that.format(that.totalData[that.columnNameIndex].toFixed(0))).attr("font-size", function (d) { if (that.showTotal) { return 36 } else { return 0 } }) that.svg.select('.dataTitle') .text(that.dataTitle).attr("font-size", function (d) { if (that.showDataTitle) { return 40 } else { return 0 } }) } // else { // // 右下角数据显示 // let tmpHeight = that.svg.attr("height") - that.margin[2]; // if ("asc" == that.sort) { // tmpHeight = that.margin[0] + 50; // if (that.isTemplate) tmpHeight = tmpHeight + 50 // } // console.log(that.sort, tmpHeight); // that.svg.select(".year").transition() // .duration(that.durationTime) // .attr("y", function () { // if (that.templateType == 'template_virus') return tmpHeight - 820 // return tmpHeight // }) // .attr("x", function () { // if (that.templateType == 'template_virus') return 300 // if (that.isTemplate) return 670 // return that.clientWidth - that.margin[1] // }) // .attr("font-size", that.fontsize) // .attr("fill", that.rectTextColor); // } } clearAllTimeout() { //for (var i = 0; i < 9999; i++) { // clearTimeout(i); // console.log(i); //} } /** * 重新播放 */ replay() { let that = this; this.clearAllTimeout(); if (that.isRun) { clearTimeout(that.timeout); if (that.timeout) that.timeout.stop(); } that.mvar.selectAll('g').remove(); let year = that.columnInnerName[2]; that.columnNameIndex = 2; that.currentData = []; that.updateChart(year, true); } /** 播放 */ play() { let that = this; clearTimeout(that.timeout); this.clearAllTimeout(); if (that.timeout) that.timeout.stop(); let year = that.columnInnerName[that.columnNameIndex]; that.currentData = []; that.updateChart(year, false); } /** 暂停 */ pause() { let that = this; clearTimeout(that.timeout); if (that.timeout) that.timeout.stop(); that.isRun = false; } /** * 渲染指定页面 * @param {*} index */ renderIndex(index) { let that = this; if (that.isRun) { //播放中不支持直接跳转 return; } that.columnNameIndex = index; let year = that.columnInnerName[that.columnNameIndex]; that.updateChart(year, true, true); } /** * 初始化 * @param {Object} obj */ init(obj) { let that = this; Object.assign(this, obj); this.getEase(); this.clearAllTimeout(); that.svg = d3.select("#" + this.el).append("svg"); that.svg.append("g").attr("class", "bcrlegend"); if (that.clientWidth == 0) { that.clientWidth = document.getElementById(this.el).clientWidth; } that.arrayToJson(); that.svg.attr("width", that.clientWidth).attr("height", that.clientHeight); let width = that.clientWidth - this.margin[1] - this.margin[3]; that.x = d3.scaleLinear().range([0, width]) that.xScale = that.x.domain([0, that.max()]) if (that.rectHeightFixed) { that.rectHeight = (that.clientHeight - that.margin[0] - that.margin[2]) / (that.barNumber + (that.barNumber - 1) * that.rectRate); } that.rectSpace = that.rectHeight * that.rectRate; if (that.isTemplate && that.templateType != 'template_virus') that.ticksNum = 0 that.gridscale = d3 .axisTop() .scale(that.xScale) .ticks(that.ticksNum) .tickPadding(12) .tickSize(-(that.clientHeight - that.margin[2] - that.margin[0] + 30), 0, 0) .tickFormat(d => { if (d < 0) { return ""; } if (that.isTemplate && d != 0 && that.templateType != 'template_virus') return ""; return that.format(d); }) //添加竖线 that.svg .append("g") .attr("class", "grid") .style("color", function () { if (that.isTemplate && that.templateType != 'template_virus') return '#ffffff' return "#A3A3A3" }) .attr("opacity", that.showAxisX ? 1 : 0.0001) .style("font-size", that.XfontSize) .call(that.gridscale); that.bar = this.svg.append("g"); that.bar.attr('transform', `translate(${this.margin[3]}, ${this.margin[0]})`) that.mvar = that.bar.append("g"); let tmpHeight = that.svg.attr("height") - that.margin[2]; if ("asc" == that.sort) { tmpHeight = that.margin[0] + 50; } that.svg.append("text").attr("class", "year") .attr("y", function () { if (that.templateType == 'template_virus') return tmpHeight - 820 return tmpHeight }) .attr("x", function () { if (that.templateType == 'template_virus') return 280 if (that.isTemplate) return 670 return that.terminal == 'mobile' ? that.clientWidth - 50 : that.clientWidth - 100 }) .text(that.columnName[2]) .attr("text-anchor", that.templateType == 'template_virus' ? "start" : "end") .attr("font-size", that.fontsize) .attr("fill", that.rectTextColor) .attr("style", "font-family:" + that.fontFamily) if (that.templateType == 'template_virus') { that.svg.append("text") .attr("y", function () { return 280 }) .attr("x", function () { if (that.showTotal) { return 175 } else { return 270 } }) .attr('class', 'dataTitle') .text(that.dataTitle) .attr("text-anchor", "center") .attr("font-size", 36) .attr("fill", that.rectTextColor); that.svg.append("rect") .attr("class", 'line1') .attr("y", function () { return 267 }) .attr("x", function () { return 110 }) .attr('width', 30) .attr('height', function () { if (that.showDataTitle || that.showTotal) { return 2 } else { return 0 } }) .attr("fill", '#FF5A5A'); that.svg.append("rect") .attr("class", 'line2') .attr("y", function () { return 267 }) .attr("x", function () { return 580 }) .attr('width', 30) .attr('height', function () { if (that.showDataTitle || that.showTotal) { return 2 } else { return 0 } }) .attr("fill", '#FF5A5A'); that.svg.append("text").text("0") .attr("style", "font-family:" + that.fontFamily) .attr("class", "total") .attr('fill', function () { return "#FF5A5A" }) .attr("text-anchor", "start") .attr("y", function () { return 278 }) .attr("x", function () { if (that.showDataTitle) { return 385 } else { return 302 } }) .attr("font-size", 40) } if (!that.showYear) { that.svg.select(".year").attr("font-size", "0") } //定义渐变色 that.colorGradient = that.svg.append("defs").append("linearGradient").attr('id', 'colorGradient').attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%") //定义文字背景渐变色 if (that.showBgGradient) { let bg = that.svg.append("defs").append("linearGradient").attr('id', 'bgGradient').attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%") bg.append("stop") .attr("offset", "0%") .attr("stop-color", that.bgGradient[0]) bg.append("stop") .attr("offset", "100%") .attr("stop-color", that.bgGradient[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(that.columnInnerName[2], true, false); 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] } }) } /** * 页面渲染 * @param {*} year */ updateChart(year, initflag, renderIndexFlag) { let that = this; if (!initflag) { return; } //console.log("updateChart:" + year + " initflag:" + initflag + " renderIndexFlag:" + renderIndexFlag); let durationTime = that.durationTime if (this.columnNameIndex < 3) durationTime = 0 if (that.rectHeightFixed) { that.rectHeight = (that.clientHeight - that.margin[0] - that.margin[2]) / (that.barNumber + (that.barNumber - 1) * that.rectRate); } that.rectSpace = that.rectHeight * that.rectRate; if (that.clientWidth == 0) { that.clientWidth = document.getElementById(this.el).clientWidth; } that.svg.attr("width", that.clientWidth).attr("height", that.clientHeight); d3.select('#colorGradient').html('') that.colorGradient.append('stop').attr('offset', '0%').attr('stop-color', that.colors[0]) that.colorGradient.append('stop').attr('offset', '100%').attr('stop-color', that.colors[1]) //数据排序 that.jsonData = that.jsonData.sort(function (a, b) { if ("desc" == that.sort) { return d3.descending(+a[year], +b[year]); } else { return d3.ascending(+a[year], +b[year]) } }); that.currentData = []; //取前几多条数据 let index = 0; for (var i = 0; i < that.jsonData.length; i++) { let tmpIdx = Number(that.jsonData[i][year]); if (that.showZero) { if (!isNaN(tmpIdx) && tmpIdx >= 0) { that.currentData[index] = that.jsonData[i]; index++; if (index == that.barNumber) { break; } } } else { if (!isNaN(tmpIdx) && tmpIdx > 0) { that.currentData[index] = that.jsonData[i]; index++; if (index == that.barNumber) { break; } } } } //数据二次排序 that.currentData.sort(function (a, b) { if ("desc" == that.sort) { return d3.descending(+a[year], +b[year]); } else { return d3.ascending(+a[year], +b[year]); } }); that.gridscale = d3 .axisTop() .scale(that.xScale) .ticks(that.ticksNum) .tickPadding(12) .tickSize(-(that.clientHeight - that.margin[2] - that.margin[0] + 30), 0, 0) .tickFormat(d => { if (d < 0) { return ""; } if (that.isTemplate && that.templateType != 'template_virus') return ""; return that.format(d); }) let width = that.clientWidth - this.margin[1] - this.margin[3]; that.x = d3.scaleLinear().range([0, width]) that.xScale = that.x.domain([0, that.max(year)]) that.gridscale.scale(that.xScale) //更新竖线位置 that.svg.select(".grid").transition() .duration(durationTime) .ease(that.d3Ease) .attr("opacity", that.showAxisX ? 1 : 0.0001) .call(that.gridscale); d3.select(".xAxis").remove(); d3.select(".grid").select(".domain").remove(); // console.log(that.currentData) //数据绑定对象 var binding = that.mvar.selectAll('g'). data(that.currentData, function (d) { return d[that.columnInnerName[0]] }); //退出排名的数据 离场动画 binding.exit().transition() .duration(durationTime) .attr("transform", function (d, i) { return "translate(0," + (that.barNumber) * (that.rectHeight + that.rectSpace) + ")"; }) .style("opacity", 0.0001).remove(); //补充新的元素 that.enterG = binding.enter().append("g"); // 新元素初始化 that.enterG.attr("transform", function (d, i) { return "translate(0," + (that.barNumber - 1) * (that.rectHeight + that.rectSpace) + ")"; }).transition() .duration(durationTime) .attr("transform", function (d, i) { return "translate(0," + i * (that.rectHeight + that.rectSpace) + ")"; }).attr("width", function (d) { return that.xScale(d[year]); }).ease(that.d3Ease); //添加rect节点 that.enterG.append("rect") .attr("class", "rect") .attr("width", function (d) { return that.xScale(d[year]); }) .attr("rx", that.rx) .attr("y", function (d, i) { return that.rectHeight / 2; }) .attr('filter', function () { if (that.templateType == 'template3') return "url(#f1)" return 'url(#empty)' }) .attr("height", that.rectHeight) .attr("fill", function (d, i) { let index = that.colorsCateory ? 1 : 0; let name = that.columnInnerName[index]; if (index == 1) { name = "category_dsd"; } if (that.isTemplate && that.gradient) return 'url(#colorGradient)' return that.colorMap.get(d[name]); }); //添加text节点 that.enterG.append("text").text("0") .attr("class", "vtips") .attr('fill', function () { // if (that.isTemplate) return that.colors[1] return that.fontColor }) .attr("x", that.vtipsOffsiteX) .attr("y", function (d, i) { return (that.rectHeight + (5 * that.YfontSize / that.rectHeight + that.rectHeight / that.barNumber)) //return that.rectHeight + i * (that.rectHeight + that.rectSpace); }) .attr("style", "font-family:" + that.fontFamily) .attr("text-anchor", "start") .attr("transform", function (d, i) { if (that.useImages) return "translate(" + (that.xScale(d[year]) + that.vtipsOffsite) + ")"; return "translate(" + (that.xScale(d[year]) + 10) + ")"; images }) .attr("font-size", that.YfontSize - 2).transition() .duration(durationTime) .tween("text", function (d) { var self = this; let num = self.textContent; let numLen = d[year].toString().split('.')[1] === undefined ? 0 : d[year].toString().split('.')[1].length var i = d3.interpolate(num, d[year]); return function (t) { let num = parseFloat(i(t)).toFixed(numLen) self.textContent = that.format(num); }; }) .ease(that.d3Ease); if (that.useImages) { that.enterG.append('image') .attr("class", "image") .attr("preserveAspectRatio", "xMidYMid meet") .attr("width", function (d, i) { if (d['image']) { let w = that.rectHeight * 3 / 2 - 5 if (w > 50) w = 50 if (that.templateType == 'template3') return that.rectHeight - 5 return w } else { return 0 } }) .attr("height", function (d, i) { if (that.templateType == 'template3') return that.rectHeight - 5 return that.rectHeight }) .attr("x", 0) .attr("y", function (d, i) { return (that.rectHeight + (8 * that.YfontSize / that.rectHeight + 1.5 * that.rectHeight / that.barNumber)) - that.rectHeight + that.imageOffsite //return that.rectHeight + i * (that.rectHeight + that.rectSpace); }) .attr("transform", function (d, i) { return "translate(" + (that.xScale(d[year]) + 10) + "," + 10 + ")"; }) .attr("xlink:href", function (d, i) { let img = d['image'] if (img) return img return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAABVCAYAAADNCyPqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAADGSURBVHhe7dAxAQAwDMCg+ffctSr4cmCA92c2TsFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjBWMFYwVjB1OwBeFHfxoh6bUcAAAAASUVORK5CYII=" }) .transition() .duration(durationTime) .ease(that.d3Ease); binding.select(".image") .transition().duration(durationTime) .attr("width", function (d, i) { if (d['image']) { let w = that.rectHeight * 3 / 2 - 5 if (w > 50) w = 50 if (that.templateType == 'template3') return that.rectHeight - 5 return w } else { return 0 } }) .attr("height", function (d, i) { if (that.templateType == 'template3') return that.rectHeight - 5 return that.rectHeight }) .attr("x", 0) .attr("y", function (d, i) { return (that.rectHeight + (8 * that.YfontSize / that.rectHeight + 1.5 * that.rectHeight / that.barNumber)) - that.rectHeight + that.imageOffsite //return that.rectHeight + i * (that.rectHeight + that.rectSpace); }).attr("text-anchor", "start") .attr("transform", function (d, i) { return "translate(" + (that.xScale(d[year]) + 10) + "," + 10 + ")"; }).ease(that.d3Ease); } //名字添加背景渐变 if (that.showBgGradient) { that.enterG.append("rect") .attr("class", "bgRect") .attr("fill", "url(#bgGradient)") .attr("height", that.YfontSize + 5) .attr("width", this.margin[3] - 4) .attr("x", -this.margin[3] + 2) .attr("y", function (d, i) { return (that.rectHeight + (8 * that.YfontSize / that.rectHeight + that.rectHeight / that.barNumber)) - that.YfontSize; }) .attr("fill-opacity", "0.6") binding.select(".bgRect").attr("height", that.YfontSize + 5) .attr("width", this.margin[3] - 4) .attr("x", -this.margin[3] + 2) .attr("y", function (d, i) { return (that.rectHeight + (8 * that.YfontSize / that.rectHeight + that.rectHeight / that.barNumber)) - that.YfontSize; }) .attr("fill-opacity", "0.6") } // 添加最左侧文本 that.enterG.append("text").attr("class", "lefttext").text(function (d) { return d[that.columnInnerName[0]]; }) .attr("x", -5) .attr("y", function (d, i) { return (that.rectHeight + (5 * that.YfontSize / that.rectHeight + that.rectHeight / that.barNumber)); }).attr("font-size", that.YfontSize) .attr("text-anchor", "end") .attr('fill', that.fontColor); // 修改最左侧文字 binding.select(".lefttext").transition().duration(durationTime) .attr("font-size", that.YfontSize) .attr("y", function (d, i) { return (that.rectHeight + (5 * that.YfontSize / that.rectHeight + that.rectHeight / that.barNumber)); }).attr('fill', that.fontColor); //进度条宽度变化动画 binding.select(".rect").transition() .duration(durationTime).attr("width", function (d) { return that.xScale(d[year]); }).attr("height", that.rectHeight).attr("y", function (d, i) { return that.rectHeight / 2; }).attr("rx", that.rx).attr("fill", function (d, i) { let index = that.colorsCateory ? 1 : 0; let name = that.columnInnerName[index]; if (index == 1) { name = "category_dsd"; } if (that.isTemplate && that.gradient) return 'url(#colorGradient)' return that.colorMap.get(d[name]); }).ease(that.d3Ease); //进度数值 binding.select(".vtips") .attr("font-size", that.YfontSize - 2) .attr('fill', function () { // if (that.isTemplate) return that.colors[1] return that.fontColor }).transition().duration(durationTime) .attr("x", that.vtipsOffsiteX) .attr("y", function (d, i) { return (that.rectHeight + (5 * that.YfontSize / that.rectHeight + that.rectHeight / that.barNumber)) //return that.rectHeight + i * (that.rectHeight + that.rectSpace); }).attr("text-anchor", "start") .tween("text", function (d) { var self = this; var i = d3.interpolate(self.textContent.replaceAll(",", ""), d[year]); return function (t) { //console.log(t) let len = 0 if (d[year].toString().split('.')[1]) len = d[year].toString().split('.')[1].length let num = parseFloat(i(t)).toFixed(len) self.textContent = that.format(num); }; }).attr("transform", function (d, i) { if (that.useImages) return "translate(" + (that.xScale(d[year]) + that.vtipsOffsite) + ")"; return "translate(" + (that.xScale(d[year]) + 10) + ")"; }).ease(that.d3Ease); let tmpHeight = that.svg.attr("height") - that.margin[2]; if ("asc" == that.sort) { tmpHeight = that.margin[0] + 50; } that.svg.select(".year").text(that.columnName[that.columnNameIndex]).attr("y", function () { if (that.templateType == 'template_virus') return tmpHeight - 820 return tmpHeight }).attr("x", function () { if (that.templateType == 'template_virus') return 280 if (that.isTemplate) return 670 return that.terminal == 'mobile' ? that.clientWidth - 50 : that.clientWidth - 100 }).attr('font-size', function () { if (that.showYear) { return that.fontsize } else { return 0 } }); if (that.templateType == 'template_virus') { that.svg.select(".total") .text(that.format(that.totalData[that.columnNameIndex].toFixed(0))).attr("font-size", function (d) { if (that.showTotal) { return 36 } else { return 0 } }) .attr("x", function () { if (that.showDataTitle) { return 385 } else { return 302 } }) that.svg.select('.dataTitle') .text(that.dataTitle).attr("font-size", function (d) { if (that.showDataTitle) { return 40 } else { return 0 } }) .attr("x", function () { if (that.showTotal) { return 175 } else { return 270 } }) that.svg.select(".line1") .attr('height', function () { if (that.showDataTitle || that.showTotal) { return 2 } else { return 0 } }) that.svg.select(".line2") .attr('height', function () { if (that.showDataTitle || that.showTotal) { return 2 } else { return 0 } }) } //进度条位置变化动画 binding.transition() .duration(durationTime) .style("opacity", 1) .attr("transform", function (d, i) { return "translate(0," + i * (that.rectHeight + that.rectSpace) + ")"; }).ease(that.d3Ease); that.updateXAxis(); if (renderIndexFlag) { return; } // 打开下一帧 if (that.columnNameIndex < that.columnName.length - 1) { if (initflag) { that.timeout = d3.timeout(function () { that.columnNameIndex++; year = that.columnInnerName[that.columnNameIndex]; that.updateChart(year) }, that.delay); } else { that.timeout = d3.timeout(function () { that.columnNameIndex++; year = that.columnInnerName[that.columnNameIndex]; that.updateChart(year) }, that.durationTime); } } else { that.isRun = false; } } /** * 更新X坐标位置 */ updateXAxis() { let that = this; if (!that.showAxisX) { that.svg.select(".grid").selectAll("text").attr('font-size', "0"); } else { that.svg.select(".grid").selectAll("text").attr('font-size', that.XfontSize); } if ("bottom" == that.xAxisPos) { that.svg.select(".grid").attr('transform', 'translate(' + that.margin[3] + ',' + that.margin[0] + ' )'); let t = that.clientHeight - that.margin[2] - that.margin[0] + 50; that.svg.select(".grid").selectAll("text").attr('transform', 'translate(' + 0 + ',' + t + ')'); } else { that.svg.select(".grid").selectAll("text").attr('transform', ""); that.svg.select(".grid").attr('transform', 'translate(' + that.margin[3] + ',' + that.margin[0] + ' )'); } } /** * 千分位格式化 * @param {String} num */ format(num) { // var reg = /\d{1,3}(?=(\d{3})+$)/g; // return (num + '').replace(reg, '$&,'); 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) } 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 } /** * 计算最大值 * @param {*} year */ max(year) { let that = this; let max = 0; if ("Dynamic" == that.scaleType) { for (var i = 0; i < that.currentData.length; i++) { let tmp = Number(that.currentData[i][year]); if (!isNaN(tmp)) { max = max > tmp ? max : tmp; } } } else if ("Fixed" == that.scaleType || "Custom" == that.scaleType) { max = that.maxValue; } return max; } arrayToJson() { let that = this; //第一行为列名 that.columnName = that.data[0]; for (let i = 0; i < that.columnName.length; i++) { that.columnInnerName[i] = "cn_" + i; //内部名称 } let data = []; let max = 0; for (var i = 1; i < that.data.length; i++) { let obj = {}; for (var j = 0; j < that.columnName.length; j++) { that.data[i][j] = that.data[i][j] + ""; if (j == 1) { obj["category_dsd"] = that.data[i][j]; } else { obj[that.columnInnerName[j]] = that.data[i][j]; } let tmp = Number(that.data[i][j]); if (!isNaN(tmp)) { max = max > tmp ? max : tmp; } } data.push(obj); } that.jsonData = data; if ("Custom" != that.scaleType) { that.maxValue = max; } this.updateColors(); if (that.useImages) this.updataImages(); } /** * 分配颜色 */ updateColors() { let that = this; that.colorMap = new Map(); if (that.colorsCateory) { //取分组 var m = new Map(); var s = new Set(); let j = 0; for (var i = 0; i < that.jsonData.length; i++) { let key = that.jsonData[i]['category_dsd']; if (!s.has(key)) { m.set(key, j); s.add(key); j++; } let index = m.get(key); let c = that.colors[index % (that.colors.length)]; that.colorMap.set(key, c) } if (that.showLegend && !that.isTemplate) { that.addLegend(m); } else { that.svg.select(".bcrlegend").selectAll("g").remove(); } } else { for (var i = 0; i < that.jsonData.length; i++) { let c = that.colors[i % (that.colors.length)]; let key = that.jsonData[i][that.columnInnerName[0]]; that.colorMap.set(key, c); } that.svg.select(".bcrlegend").selectAll("g").remove(); } } updataImages() { // let that = this; // that.imageMap = new Map(); // var m = new Map(); // var s = new Set(); // let j = 0; // that.useImages = false // for (var i = 0; i < that.jsonData.length; i++) { // let key = that.jsonData[i]['category_dsd']; // if (!s.has(key)) { // m.set(key, j); // s.add(key); // j++; // } // let index = m.get(key); // let c = that.dynamicImages[index % (that.dynamicImages.length)]; // that.imageMap.set(key, c) // if (c) that.useImages = true // } let that = this; for (var i = 0; i < that.jsonData.length; i++) { that.jsonData[i]["image"] = that.dynamicImages[i] } } /** * 显示图例 * @param {Object} m */ addLegend(m) { let that = this; //清空原图例下所有数据 that.svg.select(".bcrlegend").selectAll("g").remove(); let data = []; m.forEach(function (item, key, mapObj) { let color = that.colors[item % (that.colors.length)] let tmp = { key: key, v: item, color: color }; data.push(tmp); }); var binding = that.svg.select(".bcrlegend").selectAll("g").data(data, function (d) { return d.key; }); binding.exit().transition().duration(that.durationTime).remove(); that.svg.select(".bcrlegend").transition().duration(that.durationTime) .attr('transform', 'translate(' + ((that.unitSize - 16) * 2 + 120) + ',' + (that.margin[0] - 45 + 1.5 * (that.titleFontSize - 36)) + ' )').ease(that.d3Ease); 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.key.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 || 25 offsetText = parseInt(d.key.length * 5) + parseInt(beforeOffset) + 20 + that.legendFontSize * 4 return 'translate(' + beforeOffset + ',' + 7 + ' )'; //return 'translate(' + (i * 75 + 12) + ',' + 10 + ' )'; }).text(function (d, i) { return d.key; }) // binding.selectAll("rect").transition() // .duration(that.durationTime).attr("fill", function(d, i) { // console.log(that.colorMap.get(d['key']) + " = " + d['key'] + " = " + i); // return that.colorMap.get(d['key']); // }).attr("rx", that.rx).attr("font-size", that.legendFontSize).ease(d3.easeLinear); } } export default BarChartRace;