Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化锥型图 config.data[].value为0时 js除法报错 svg绘图无高度导致字体重叠样式错误问题 #281

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
308 changes: 158 additions & 150 deletions src/components/conicalColumnChart/src/main.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
<template>
<div class="dv-conical-column-chart" :ref="ref">
<svg :width="width" :height="height">
<g
v-for="(item, i) in column"
:key="i"
>
<path
:d="item.d"
:fill="mergedConfig.columnColor"
/>
<g v-for="(item, i) in column" :key="i">
<path :d="item.d" :fill="mergedConfig.columnColor" />
<text
:style="`fontSize:${mergedConfig.fontSize}px`"
:fill="mergedConfig.textColor"
Expand Down Expand Up @@ -40,180 +34,194 @@
</template>

<script>
import autoResize from '../../../mixin/autoResize'
import autoResize from "../../../mixin/autoResize";

import { deepMerge } from '@jiaminghi/charts/lib/util/index'
import { deepMerge } from "@jiaminghi/charts/lib/util/index";

import { deepClone } from '@jiaminghi/c-render/lib/plugin/util'
import { deepClone } from "@jiaminghi/c-render/lib/plugin/util";

export default {
name: 'DvConicalColumnChart',
mixins: [autoResize],
props: {
config: {
type: Object,
default: () => ({})
}
},
data () {
return {
ref: 'conical-column-chart',

defaultConfig: {
/**
* @description Chart data
* @type {Array<Object>}
* @default data = []
*/
data: [],
/**
* @description Chart img
* @type {Array<String>}
* @default img = []
*/
img: [],
/**
* @description Chart font size
* @type {Number}
* @default fontSize = 12
*/
fontSize: 12,
/**
* @description Img side length
* @type {Number}
* @default imgSideLength = 30
*/
imgSideLength: 30,
/**
* @description Column color
* @type {String}
* @default columnColor = 'rgba(0, 194, 255, 0.4)'
*/
columnColor: 'rgba(0, 194, 255, 0.4)',
/**
* @description Text color
* @type {String}
* @default textColor = '#fff'
*/
textColor: '#fff',
/**
* @description Show value
* @type {Boolean}
* @default showValue = false
*/
showValue: false
export default {
name: "DvConicalColumnChart",
mixins: [autoResize],
props: {
config: {
type: Object,
default: () => ({}),
},

mergedConfig: null,

column: []
}
},
watch: {
config () {
const { calcData } = this

calcData()
}
},
methods: {
afterAutoResizeMixinInit () {
const { calcData } = this

calcData()
},
onResize () {
const { calcData } = this
data() {
return {
ref: "conical-column-chart",

defaultConfig: {
/**
* @description Chart data
* @type {Array<Object>}
* @default data = []
*/
data: [],
/**
* @description Chart img
* @type {Array<String>}
* @default img = []
*/
img: [],
/**
* @description Chart font size
* @type {Number}
* @default fontSize = 12
*/
fontSize: 12,
/**
* @description Img side length
* @type {Number}
* @default imgSideLength = 30
*/
imgSideLength: 30,
/**
* @description Column color
* @type {String}
* @default columnColor = 'rgba(0, 194, 255, 0.4)'
*/
columnColor: "rgba(0, 194, 255, 0.4)",
/**
* @description Text color
* @type {String}
* @default textColor = '#fff'
*/
textColor: "#fff",
/**
* @description Show value
* @type {Boolean}
* @default showValue = false
*/
showValue: false,
},

mergedConfig: null,

column: [],
};
},
watch: {
config() {
const { calcData } = this;

calcData()
calcData();
},
},
calcData () {
const { mergeConfig, initData, calcSVGPath } = this
methods: {
afterAutoResizeMixinInit() {
const { calcData } = this;

calcData();
},
onResize() {
const { calcData } = this;

mergeConfig()
calcData();
},
calcData() {
const { mergeConfig, initData, calcSVGPath } = this;

initData()
mergeConfig();

calcSVGPath()
},
mergeConfig () {
const { defaultConfig, config } = this
initData();

this.mergedConfig = deepMerge(deepClone(defaultConfig, true), config || {})
},
initData () {
const { mergedConfig } = this
let { data } = mergedConfig
calcSVGPath();
},
mergeConfig() {
const { defaultConfig, config } = this;

data = deepClone(data, true)
this.mergedConfig = deepMerge(
deepClone(defaultConfig, true),
config || {}
);
},
initData() {
const { mergedConfig } = this;
let { data } = mergedConfig;

data.sort(({ value: a }, { value: b }) => {
if (a > b) return -1
if (a < b) return 1
if (a === b) return 0
})
data = deepClone(data, true);

const max = data[0] ? data[0].value : 10
data.sort(({ value: a }, { value: b }) => {
if (a > b) return -1;
if (a < b) return 1;
if (a === b) return 0;
});

data = data.map(item => ({
...item,
percent: item.value / max
}))
const max = data[0] ? data[0].value : 10;

mergedConfig.data = data
},
calcSVGPath () {
const { mergedConfig, width, height } = this
data = data.map((item) => ({
...item,
percent: this.computePercent(item.value, max),
}));

mergedConfig.data = data;
},
computePercent(value, max) {
if (value) {
if (value / max < 0.2) {
return 0.2;
} else {
return value / max;
}
} else {
return 0.2;
}
},
calcSVGPath() {
const { mergedConfig, width, height } = this;

const { imgSideLength, fontSize, data } = mergedConfig
const { imgSideLength, fontSize, data } = mergedConfig;

const itemNum = data.length
const gap = width / (itemNum + 1)
const itemNum = data.length;
const gap = width / (itemNum + 1);

const useAbleHeight = height - imgSideLength - fontSize - 5
const svgBottom = height - fontSize - 5
const useAbleHeight = height - imgSideLength - fontSize - 5;
const svgBottom = height - fontSize - 9;

this.column = data.map((item, i) => {
const { percent } = item
this.column = data.map((item, i) => {
const { percent } = item;

const middleXPos = gap * (i + 1)
const leftXPos = gap * i
const rightXpos = gap * (i + 2)
const middleXPos = gap * (i + 1);
const leftXPos = gap * i;
const rightXpos = gap * (i + 2);

const middleYPos = svgBottom - useAbleHeight * percent
const controlYPos = useAbleHeight * percent * 0.6 + middleYPos
const middleYPos = svgBottom - useAbleHeight * percent;
const controlYPos = useAbleHeight * percent * 0.6 + middleYPos;

const d = `
const d = `
M${leftXPos}, ${svgBottom}
Q${middleXPos}, ${controlYPos} ${middleXPos},${middleYPos}
M${middleXPos},${middleYPos}
Q${middleXPos}, ${controlYPos} ${rightXpos},${svgBottom}
L${leftXPos}, ${svgBottom}
Z
`

const textY = (svgBottom + middleYPos) / 2 + fontSize / 2

return {
...item,
d,
x: middleXPos,
y: middleYPos,
textY
}
})
}
}
}
`;

const textY = (svgBottom + middleYPos) / 2 + fontSize / 2;

return {
...item,
d,
x: middleXPos,
y: middleYPos,
textY,
};
});
},
},
};
</script>

<style lang="less">
.dv-conical-column-chart {
width: 100%;
height: 100%;
.dv-conical-column-chart {
width: 100%;
height: 100%;

text {
text-anchor: middle;
text {
text-anchor: middle;
}
}
}
</style>