Skip to content
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>