echarts饼图legend百分比计算时四舍五入有误差的解决方案
// 传入参数(数组数据,数组下标,精度),底下有例子调用
var getPercentValue = function (valueList, idx, precision) {
// 判断是否为空
if (!valueList[idx]) {
return 0;
}
// 求和
var sum = valueList.reduce(function (acc, val) {
return acc + (isNaN(val) ? 0 : val);
}, 0)
if (sum === 0) {
return 0;
}
// 10的2次幂是100,用于计算精度。
var digits = Math.pow(10, precision);
// 扩大比例100,
var votesPerQuota = valueList.map(function (val) {
return (isNaN(val) ? 0 : val) / sum * digits * 100;
})
// 总数,扩大比例意味的总数要扩大
var targetSeats = digits * 100;
// 再向下取值,组成数组
var seats = votesPerQuota.map(function (votes) {
return Math.floor(votes);
})
// 再新计算合计,用于判断与总数量是否相同,相同则占比会100%
var currentSum = seats.reduce(function (acc, val) {
return acc + val;
}, 0)
// 余数部分的数组:原先数组减去向下取值的数组,得到余数部分的数组
var remainder = votesPerQuota.map(function (votes, idx) {
return votes - seats[idx];
})
// 给最大最大的余额加1,凑个占比100%;
while (currentSum < targetSeats) {
// 找到下一个最大的余额,给其加1
var max = Number.NEGATIVE_INFINITY;
var maxId = null;
for (var i = 0, len = remainder.length; i < len; ++i) {
if (remainder[i] > max) {
max = remainder[i];
maxId = i;
}
}
// 对最大项余额加1
++seats[maxId];
// 已经增加最大余数加1,则下次判断就可以不需要再判断这个余额数。
remainder[maxId] = 0;
// 总的也要加1,为了判断是否总数是否相同,跳出循环。
++currentSum;
}
// 这时候的seats就会总数占比会100%
return seats[idx] / digits
}
//调用
getPercentValue(arr,0,2)
echarts迁徙地图
<template>
<div id="moveMapChart" style=" 100%; height: 500px"></div>
</template>
<script>
import resize from "@/util/resize"
import * as echarts from "echarts"
import "./china.js"
export default {
name:"moveMapChart",
mixins:[resize],
data() {
return {
data:[],
charts:null,
timeFn:null,
geoCoordMap:{},
cityName:""
};
},
props:{
comJson:{
type:Object,
default:function(){
return {linaData:[],cityList:[],geoCoord:{},config:{}}
}
}
},
watch:{
comJson:{
handler:function(){
this.whatfuck()
},
deep:true
}
},
computed: {},
created(){
this.getStore();
},
mounted(){
this.whatfuck()
},
methods: {
let that = this
if(that.charts){
that.charts.dispose()
}
that.charts=that.$echarts.init(document.getElementById("moveMapChart"))
let cityList = that.comJson.cityList.length === 0?[that.cityName]:this.comJson.cityList
let text = that.comJson.config.text||""
that.geoCoordMap = that.comJson.geoCoord
let convertData = function(data){
let res = []
for (let i = 0; i < data.length; i++) {
let dataItem = data[i]
let fromCoord = that.geoCoordMap[dataItem[0].name]
let toCoord = that.geoCoordMap[dataItem[1].name]
if(fromCoord && toCoord){
res.push({
coords:[fromCoord,toCoord],
info:[dataItem[0].name,dataItem[1].name,dataItem[0].value]
})
}
}
return res
}
let series = [
{
type:"effectScatter",
name:"qianXi",
rippleEffect:{
brushType:"fill"
},
coordinateSystem:"geo",
symbolSize:10,
label:{
show:true,
position:"right",
formatter:"{b}"
},
itemStyle:{
color:"#00ffff"
},
data:cityList.map(function(item){
return {name:item,value:that.geoCoordMap[item]}
}),
zlevel:2
}
]
[["qianXi",that.conJson.lineData]].forEach(function(item,i){
series.push(
{
type:"lines",
name:item[0],
zlevel:2,
effect:{
show:true,
constantSpeed:20,
symbol:"triangle",
symbolSize:6,
trailLength:0
},
lineStyle:{
color:"#0ff",
1.5,
opacity:0.4,
curveness:0.2
},
label:{
show:true
},
data:convertData(item[1])
}
)
})
let mapBoxOption={
backgroundColor:"#0c1a3c",
title:{
text:text,
textStyle:{
color:"#fff"
},
left:"center",
top:26
},
tooltip:{
show:true
},
geo:{
map:"china",
roam:true,
aspectScale:0.75,
zoom:1,
label:{
show:false,
textStyle:{
color:"#00a0c9"
}
},
itemStyle:{
areaColor:"#0f1f48",
borderColor:"#3598dc"
},
emphasis:{
label:{
show:false,
textStyle:{
color:"#00a0c9"
}
},
itemStyle:{
borderWidth:0,
borderColor:"#0066ba",
areaColor:"#0f1f48",
shadowColor:"rgba(0,0,0,0.5)"
}
},
left:"16%",
top:"12%",
tooltip:{
show:true,
formatter:function(par){
if(par.componentType==="series"){
if(par.data.info){
return (par.data.info[0]+"->"+par.data.info[1]+":"+par.data.info[2])
}
}
}else{
return ""
}
}
},
series:series
}
that.charts.setOption(mapBoxOption)
that.charts.resize()
},
getStore(){
this.cityName = JSON.parse(window.localStorage.getItem("store")).user.userInfo.organizationName
}
};
</script>
<style></style>
echarts热力图
<template>
<div :id="id" style=" 100%; height: 100%"></div>
</template>
<script>
import resize from "@/util/resize";
export default {
mixins: [resize],
name: "heatMap",
props: {
id: {
type: String,
default: "heatMap",
},
comJSON: {
type: Object,
default: function () {
return { data: {}, config: {} };
},
},
},
data() {
return {
charts: null,
};
},
watch: {
comJSON: {
handler: function () {
this.drawLineChart();
},
deep: true,
},
},
mounted() {
this.drawLineChart();
},
methods: {
drawLineChart() {
//set data and config
let titleName = this.comJSON.data.title ? this.comJSON.data.title : "";
let min = this.comJSON.config.min ? this.comJSON.config.min : 0;
let max = this.comJSON.config.max ? this.comJSON.config.max : 100;
let xName =
this.comJSON.data.xArray && this.comJSON.data.xArray.length
? this.comJSON.data.xArray
: [];
let yName =
this.comJSON.data.yArray && this.comJSON.data.yArray.length
? this.comJSON.data.yArray
: [];
let chartData =
this.comJSON.data.chartData && this.comJSON.data.chartData.length
? this.comJSON.data.chartData
: [];
chartData = chartData.map(function (item) {
return [item[0], item[1], item[2] || "-"];
});
let series = [];
let option = {
title: {
text: titleName,
top: "4%",
left: "center",
},
tooltip: {
position: "top",
},
grid: {
height: "auto",
top: "16%",
},
xAxis: {
type: "category",
data: xName,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
splitArea: {
show: true,
},
},
yAxis: {
type: "category",
name: "单位:面积",
data: yName,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
splitArea: {
show: true,
},
},
visualMap: {
min: min,
max: max,
inRange: {
color: ["#8fdffd", "#8ec8fe", "#59adfc", "#2e99fd", "#3082fe"],
},
calculable: true,
inverse: true,
top: "10%",
left: "center",
orient: "horizontal",
type: "piecewise",
},
series: [
{
type: "heatmap",
data: chartData,
label: {
show: true,
},
itemStyle: {
borderWidth: "2",
borderColor: "#fff",
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowColor: "rgba(0,0,0,0.5)",
},
},
},
],
};
if (this.charts) {
this.charts.dispose();
}
this.charts = this.$echarts.init(document.getElementById(this.id));
this.charts.setOption(option, true);
this.charts.resize();
},
},
};
</script>
<style lang="scss" scoped></style>