feat(视图): 视图echarts 支持 大小 调整

This commit is contained in:
junjie 2021-03-19 14:28:38 +08:00
parent f88e8ec777
commit 7b24b457e9
11 changed files with 335 additions and 26 deletions

View File

@ -615,7 +615,29 @@ export default {
color_elegant: '淡雅',
color_technology: '科技',
color_simple: '简洁',
not_alpha: '不透明度'
not_alpha: '不透明度',
size: '大小',
bar_width: '柱宽',
bar_gap: '柱间隔',
adapt: '自适应',
line_width: '线宽',
line_type: '线型',
line_symbol: '折点',
line_symbol_size: '折点大小',
line_type_solid: '实线',
line_type_dashed: '虚线',
line_symbol_circle: '圆形',
line_symbol_emptyCircle: '空心圆',
line_symbol_rect: '矩形',
line_symbol_roundRect: '圆角矩形',
line_symbol_triangle: '三角形',
line_symbol_diamond: '菱形',
line_symbol_pin: '钉子',
line_symbol_arrow: '箭头',
line_symbol_none: '无',
pie_inner_radius: '内径',
pie_outer_radius: '外径',
funnel_width: '宽度'
},
dataset: {
datalist: '数据集',

View File

@ -15,9 +15,20 @@ export function baseBarOption(chart_option, chart) {
chart_option.xAxis.data = chart.data.x
for (let i = 0; i < chart.data.series.length; i++) {
const y = chart.data.series[i]
// color
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}
// size
if (customAttr.size) {
if (customAttr.size.barDefault) {
y.barWidth = null
y.barGap = null
} else {
y.barWidth = customAttr.size.barWidth
y.barGap = customAttr.size.barGap
}
}
y.type = 'bar'
chart_option.legend.data.push(y.name)
chart_option.series.push(y)
@ -55,9 +66,20 @@ export function horizontalBarOption(chart_option, chart) {
chart_option.yAxis.data = chart.data.x
for (let i = 0; i < chart.data.series.length; i++) {
const y = chart.data.series[i]
// color
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}
// size
if (customAttr.size) {
if (customAttr.size.barDefault) {
y.barWidth = null
y.barGap = null
} else {
y.barWidth = customAttr.size.barWidth
y.barGap = customAttr.size.barGap
}
}
y.type = 'bar'
chart_option.legend.data.push(y.name)
chart_option.series.push(y)

View File

@ -3,6 +3,18 @@ export const DEFAULT_COLOR_CASE = {
colors: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
alpha: 100
}
export const DEFAULT_SIZE = {
barDefault: true,
barWidth: 40,
barGap: 0.4,
lineWidth: 1,
lineType: 'solid',
lineSymbol: 'emptyCircle',
lineSymbolSize: 4,
pieInnerRadius: 0,
pieOuterRadius: 60,
funnelWidth: 80
}
export const BASE_BAR = {
title: {
text: ''

View File

@ -14,13 +14,19 @@ export function baseFunnelOption(chart_option, chart) {
chart_option.title.text = chart.title
if (chart.data.series.length > 0) {
chart_option.series[0].name = chart.data.series[0].name
// size
if (customAttr.size) {
chart_option.series[0].width = customAttr.size.funnelWidth + '%'
}
const valueArr = chart.data.series[0].data
// max value
chart_option.series[0].max = Math.max.apply(Math, valueArr)
for (let i = 0; i < valueArr.length; i++) {
const y = {
name: chart.data.x[i],
value: valueArr[i]
}
// color
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}

View File

@ -15,9 +15,19 @@ export function baseLineOption(chart_option, chart) {
chart_option.xAxis.data = chart.data.x
for (let i = 0; i < chart.data.series.length; i++) {
const y = chart.data.series[i]
// color
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}
// size
if (customAttr.size) {
y.symbol = customAttr.size.lineSymbol
y.symbolSize = customAttr.size.lineSymbolSize
y.lineStyle = {
width: customAttr.size.lineWidth,
type: customAttr.size.lineType
}
}
y.type = 'line'
chart_option.legend.data.push(y.name)
chart_option.series.push(y)

View File

@ -14,12 +14,17 @@ export function basePieOption(chart_option, chart) {
chart_option.title.text = chart.title
if (chart.data.series.length > 0) {
chart_option.series[0].name = chart.data.series[0].name
// size
if (customAttr.size) {
chart_option.series[0].radius = [customAttr.size.pieInnerRadius + '%', customAttr.size.pieOuterRadius + '%']
}
const valueArr = chart.data.series[0].data
for (let i = 0; i < valueArr.length; i++) {
const y = {
name: chart.data.x[i],
value: valueArr[i]
}
// color
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}

View File

@ -0,0 +1,73 @@
<template>
<div class="Echarts" style="height: 100%;display: flex;margin-top: 10px;">
<div id="echart" style="width: 100%;height: 100%;" />
</div>
</template>
<script>
import { BASE_BAR, BASE_LINE, HORIZONTAL_BAR, BASE_PIE, BASE_FUNNEL } from '../chart/chart'
import { baseBarOption, stackBarOption, horizontalBarOption, horizontalStackBarOption } from '../chart/bar/bar'
import { baseLineOption } from '../chart/line/line'
import { basePieOption } from '../chart/pie/pie'
import { baseFunnelOption } from '../chart/funnel/funnel'
export default {
name: 'ChartComponentView',
props: {
chart: {
type: Object,
required: true
}
},
data() {
return {
myChart: {}
}
},
watch: {
chart() {
this.drawEcharts()
}
},
mounted() {
// domecharts
this.myChart = this.$echarts.init(document.getElementById('echart'))
},
methods: {
drawEcharts() {
const chart = this.chart
let chart_option = {}
// todo type
if (chart.type === 'bar') {
chart_option = baseBarOption(JSON.parse(JSON.stringify(BASE_BAR)), chart)
} else if (chart.type === 'bar-stack') {
chart_option = stackBarOption(JSON.parse(JSON.stringify(BASE_BAR)), chart)
} else if (chart.type === 'bar-horizontal') {
chart_option = horizontalBarOption(JSON.parse(JSON.stringify(HORIZONTAL_BAR)), chart)
} else if (chart.type === 'bar-horizontal-stack') {
chart_option = horizontalStackBarOption(JSON.parse(JSON.stringify(HORIZONTAL_BAR)), chart)
} else if (chart.type === 'line') {
chart_option = baseLineOption(JSON.parse(JSON.stringify(BASE_LINE)), chart)
} else if (chart.type === 'pie') {
chart_option = basePieOption(JSON.parse(JSON.stringify(BASE_PIE)), chart)
} else if (chart.type === 'funnel') {
chart_option = baseFunnelOption(JSON.parse(JSON.stringify(BASE_FUNNEL)), chart)
}
console.log(chart_option)
this.myEcharts(chart_option)
},
myEcharts(option) {
//
const chart = this.myChart
setTimeout(chart.setOption(option, true), 500)
window.onresize = function() {
chart.resize()
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -18,11 +18,12 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('chart.not_alpha')" class="form-item">
<el-slider v-model="colorForm.alpha" show-input :show-input-controls="false" input-size="mini" @change="changeColorCase" />
<el-form-item :label="$t('chart.not_alpha')" class="form-item form-item-slider">
<el-slider v-model="colorForm.alpha" show-input input-size="mini" @change="changeColorCase" />
</el-form-item>
</el-form>
</el-col>
<el-button slot="reference" size="mini" class="shape-item">{{ $t('chart.color') }}<i class="el-icon-setting el-icon--right" /></el-button>
</el-popover>
<!--todo other color attr-->
@ -131,11 +132,20 @@ export default {
padding: 6px;
border: none;
}
.form-item-slider>>>.el-form-item__label{
font-size: 12px;
line-height: 38px;
}
.form-item>>>.el-form-item__label{
font-size: 12px;
}
.el-select-dropdown__item{
padding: 0 20px;
}
span{font-size: 12px}
span{
font-size: 12px
}
.el-form-item{
margin-bottom: 6px;
}
</style>

View File

@ -0,0 +1,139 @@
<template>
<div>
<div style="width:100%;height: 32px;margin:0;padding:0 4px;border-radius: 4px;border: 1px solid #DCDFE6;display: flex;align-items: center;">
<el-popover
placement="right"
width="400"
trigger="click"
>
<el-col>
<el-form v-if="chart.type && chart.type.includes('bar')" ref="sizeFormBar" :model="sizeForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.adapt')" class="form-item">
<el-checkbox v-model="sizeForm.barDefault" @change="changeBarSizeCase">{{ $t('chart.adapt') }}</el-checkbox>
</el-form-item>
<el-form-item :label="$t('chart.bar_width')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.barWidth" :disabled="sizeForm.barDefault" show-input input-size="mini" :min="0" :max="80" @change="changeBarSizeCase" />
</el-form-item>
<el-form-item :label="$t('chart.bar_gap')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.barGap" :disabled="sizeForm.barDefault" show-input input-size="mini" :min="0" :max="5" :step="0.1" @change="changeBarSizeCase" />
</el-form-item>
</el-form>
<el-form v-if="chart.type && chart.type.includes('line')" ref="sizeFormLine" :model="sizeForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.line_width')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.lineWidth" show-input input-size="mini" :min="0" :max="10" @change="changeBarSizeCase" />
</el-form-item>
<el-form-item :label="$t('chart.line_type')" class="form-item">
<el-radio-group v-model="sizeForm.lineType" @change="changeBarSizeCase">
<el-radio label="solid">{{ $t('chart.line_type_solid') }}</el-radio>
<el-radio label="dashed">{{ $t('chart.line_type_dashed') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.line_symbol')" class="form-item">
<el-select v-model="sizeForm.lineSymbol" :placeholder="$t('chart.line_symbol')" @change="changeBarSizeCase">
<el-option
v-for="item in lineSymbolOptions"
:key="item.value"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="$t('chart.line_symbol_size')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.lineSymbolSize" show-input input-size="mini" :min="0" :max="20" @change="changeBarSizeCase" />
</el-form-item>
</el-form>
<el-form v-if="chart.type && chart.type.includes('pie')" ref="sizeFormPie" :model="sizeForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.pie_inner_radius')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.pieInnerRadius" show-input input-size="mini" :min="0" :max="100" @change="changeBarSizeCase" />
</el-form-item>
<el-form-item :label="$t('chart.pie_outer_radius')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.pieOuterRadius" show-input input-size="mini" :min="0" :max="100" @change="changeBarSizeCase" />
</el-form-item>
</el-form>
<el-form v-if="chart.type && chart.type.includes('funnel')" ref="sizeFormPie" :model="sizeForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.funnel_width')" class="form-item form-item-slider">
<el-slider v-model="sizeForm.funnelWidth" show-input input-size="mini" :min="0" :max="100" @change="changeBarSizeCase" />
</el-form-item>
</el-form>
</el-col>
<el-button slot="reference" size="mini" class="shape-item">{{ $t('chart.size') }}<i class="el-icon-setting el-icon--right" /></el-button>
</el-popover>
<!--todo other size attr-->
</div>
</div>
</template>
<script>
import { DEFAULT_SIZE } from '../../chart/chart'
export default {
name: 'SizeSelector',
props: {
chart: {
type: Object,
required: true
}
},
data() {
return {
sizeForm: JSON.parse(JSON.stringify(DEFAULT_SIZE)),
lineSymbolOptions: [
{ name: this.$t('chart.line_symbol_none'), value: 'none' },
{ name: this.$t('chart.line_symbol_emptyCircle'), value: 'emptyCircle' },
{ name: this.$t('chart.line_symbol_circle'), value: 'circle' },
{ name: this.$t('chart.line_symbol_rect'), value: 'rect' },
{ name: this.$t('chart.line_symbol_roundRect'), value: 'roundRect' },
{ name: this.$t('chart.line_symbol_triangle'), value: 'triangle' },
{ name: this.$t('chart.line_symbol_diamond'), value: 'diamond' },
{ name: this.$t('chart.line_symbol_pin'), value: 'pin' },
{ name: this.$t('chart.line_symbol_arrow'), value: 'arrow' }
]
}
},
watch: {
'chart': {
handler: function() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.customAttr) {
const customAttr = JSON.parse(chart.customAttr)
if (customAttr.size) {
this.sizeForm = customAttr.size
}
}
}
}
},
mounted() {
},
methods: {
changeBarSizeCase() {
this.$emit('onSizeChange', this.sizeForm)
}
}
}
</script>
<style scoped lang="scss">
.shape-item{
padding: 6px;
border: none;
}
.form-item-slider>>>.el-form-item__label{
font-size: 12px;
line-height: 38px;
}
.form-item>>>.el-form-item__label{
font-size: 12px;
}
.el-select-dropdown__item{
padding: 0 20px;
}
span{font-size: 12px}
.el-form-item{
margin-bottom: 6px;
}
</style>

View File

@ -211,7 +211,7 @@
<script>
import { post } from '@/api/chart/chart'
import TableSelector from '../view/TableSelector'
import { DEFAULT_COLOR_CASE } from '../chart/chart'
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '../chart/chart'
export default {
name: 'Group',
@ -506,7 +506,8 @@ export default {
view.tableId = this.table.id
view.type = 'bar'
view.customAttr = JSON.stringify({
color: DEFAULT_COLOR_CASE
color: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE
})
post('/chart/view/save', view).then(response => {
this.selectTableFlag = false

View File

@ -78,21 +78,24 @@
<span>{{ $t('chart.chart_type') }}</span>
<el-row>
<div class="chart-type">
<!--TODO 这里要替换好看点的图标-->
<el-radio v-model="view.type" label="bar"><svg-icon icon-class="bar" class="chart-icon" /></el-radio>
<el-radio v-model="view.type" label="bar-stack"><svg-icon icon-class="bar-stack" class="chart-icon" /></el-radio>
<el-radio v-model="view.type" label="bar-horizontal"><svg-icon icon-class="bar-horizontal" class="chart-icon" /></el-radio>
<el-radio v-model="view.type" label="bar-horizontal-stack"><svg-icon icon-class="bar-stack-horizontal" class="chart-icon" /></el-radio>
<el-radio v-model="view.type" label="line"><svg-icon icon-class="line" class="chart-icon" /></el-radio>
<el-radio v-model="view.type" label="pie"><svg-icon icon-class="pie" class="chart-icon" /></el-radio>
<el-radio v-model="view.type" label="funnel"><svg-icon icon-class="funnel" class="chart-icon" /></el-radio>
<!--TODO 这里要替换好看点的图标UI标签可以重新定义-->
<el-radio-group v-model="view.type" @change="save">
<el-radio value="bar" label="bar"><svg-icon icon-class="bar" class="chart-icon" /></el-radio>
<el-radio value="bar-stack" label="bar-stack"><svg-icon icon-class="bar-stack" class="chart-icon" /></el-radio>
<el-radio value="bar-horizontal" label="bar-horizontal"><svg-icon icon-class="bar-horizontal" class="chart-icon" /></el-radio>
<el-radio value="bar-horizontal-stack" label="bar-horizontal-stack"><svg-icon icon-class="bar-stack-horizontal" class="chart-icon" /></el-radio>
<el-radio value="line" label="line"><svg-icon icon-class="line" class="chart-icon" /></el-radio>
<el-radio value="pie" label="pie"><svg-icon icon-class="pie" class="chart-icon" /></el-radio>
<el-radio value="funnel" label="funnel"><svg-icon icon-class="funnel" class="chart-icon" /></el-radio>
</el-radio-group>
</div>
</el-row>
</div>
<div style="height: 45%;overflow:auto;border-top: 1px solid #e6e6e6">
<el-tabs type="card" :stretch="true" class="tab-header">
<el-tab-pane :label="$t('chart.shape_attr')" class="padding-lr">
<color-selector :chart="chart" @onColorChange="onColorChange" />
<color-selector class="attr-selector" :chart="chart" @onColorChange="onColorChange" />
<size-selector class="attr-selector" :chart="chart" @onSizeChange="onSizeChange" />
</el-tab-pane>
<el-tab-pane :label="$t('chart.module_style')" class="padding-lr">TODO</el-tab-pane>
</el-tabs>
@ -138,7 +141,7 @@
</el-row>
</el-row>
<chart-component :chart="chart" />
<chart-component-view :chart="chart" style="height: 80%" />
</el-row>
</el-col>
</el-row>
@ -150,14 +153,15 @@ import { post } from '@/api/dataset/dataset'
import draggable from 'vuedraggable'
import DimensionItem from '../components/DimensionItem'
import QuotaItem from '../components/QuotaItem'
import ChartComponent from '../components/ChartComponent'
import ChartComponentView from '../components/ChartComponentView'
// shape attr
import { DEFAULT_COLOR_CASE } from '../chart/chart'
import ColorSelector from '../components/ColorSelector'
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '../chart/chart'
import ColorSelector from '../components/shape_attr/ColorSelector'
import SizeSelector from '../components/shape_attr/SizeSelector'
export default {
name: 'ChartEdit',
components: { ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
components: { SizeSelector, ColorSelector, ChartComponentView, QuotaItem, DimensionItem, draggable },
data() {
return {
table: {},
@ -170,7 +174,8 @@ export default {
type: 'bar',
title: '',
customAttr: {
color: DEFAULT_COLOR_CASE
color: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE
}
},
//
@ -206,11 +211,6 @@ export default {
},
watch: {
'view.type': {
handler: function() {
this.save()
}
}
},
created() {
// this.get(this.$store.state.chart.viewId);
@ -379,6 +379,11 @@ export default {
onColorChange(val) {
this.view.customAttr.color = val
this.save()
},
onSizeChange(val) {
this.view.customAttr.size = val
this.save()
}
}
}
@ -478,4 +483,8 @@ export default {
.el-radio>>>.el-radio__label{
padding-left: 0;
}
.attr-selector{
margin: 2px 0;
}
</style>