feat: 新增自定义颜色弹窗

This commit is contained in:
奔跑的面条
2023-02-25 22:00:55 +08:00
parent 49d8c35747
commit 8cb711b892
14 changed files with 817 additions and 30 deletions
+6
View File
@@ -1,4 +1,5 @@
import { import {
Add as AddIcon,
Close as CloseIcon, Close as CloseIcon,
Remove as RemoveIcon, Remove as RemoveIcon,
Resize as ResizeIcon, Resize as ResizeIcon,
@@ -52,6 +53,7 @@ import {
ColorWand as ColorWandIcon, ColorWand as ColorWandIcon,
ArrowBack as ArrowBackIcon, ArrowBack as ArrowBackIcon,
ArrowForward as ArrowForwardIcon, ArrowForward as ArrowForwardIcon,
ArrowDown as ArrowDownIcon,
Planet as PawIcon, Planet as PawIcon,
Search as SearchIcon, Search as SearchIcon,
ChevronUpOutline as ChevronUpOutlineIcon, ChevronUpOutline as ChevronUpOutlineIcon,
@@ -101,6 +103,8 @@ import {
} from '@vicons/carbon' } from '@vicons/carbon'
const ionicons5 = { const ionicons5 = {
// 新增
AddIcon,
// 帮助(问号) // 帮助(问号)
HelpOutlineIcon, HelpOutlineIcon,
// 添加 // 添加
@@ -206,6 +210,8 @@ const ionicons5 = {
ArrowBackIcon, ArrowBackIcon,
// 前进 // 前进
ArrowForwardIcon, ArrowForwardIcon,
// 向下
ArrowDownIcon,
// 狗爪 // 狗爪
PawIcon, PawIcon,
// 搜索(放大镜) // 搜索(放大镜)
+2
View File
@@ -57,6 +57,7 @@ import {
NProgress, NProgress,
NDatePicker, NDatePicker,
NGrid, NGrid,
NGi,
NGridItem, NGridItem,
NList, NList,
NListItem, NListItem,
@@ -160,6 +161,7 @@ const naive = create({
NProgress, NProgress,
NDatePicker, NDatePicker,
NGrid, NGrid,
NGi,
NGridItem, NGridItem,
NList, NList,
NListItem, NListItem,
+3 -15
View File
@@ -31,6 +31,9 @@ export const chartColors = {
// 默认主题 // 默认主题
export const defaultTheme = 'dark' export const defaultTheme = 'dark'
// 默认展示的选择器颜色列表
export const swatchesColors = ['#232324', '#2a2a2b', '#313132', '#373739', '#757575', '#e0e0e0', '#eeeeee', '#fafafa']
// 主题色列表 // 主题色列表
export type ChartColorsNameType = keyof typeof chartColorsName export type ChartColorsNameType = keyof typeof chartColorsName
export const chartColorsName = { export const chartColorsName = {
@@ -48,21 +51,6 @@ export const chartColorsName = {
roma: '罗马红' roma: '罗马红'
} }
// 主题色列表
export const chartColorsshow = {
dark: 'linear-gradient(to right, #4992ff 0%, #7cffb2 100%)',
customed: 'linear-gradient(to right, #5470c6 0%, #91cc75 100%)',
macarons: 'linear-gradient(to right, #2ec7c9 0%, #b6a2de 100%)',
walden: 'linear-gradient(to right, #3fb1e3 0%, #6be6c1 100%)',
purplePassion: 'linear-gradient(to right, #9b8bba 0%, #e098c7 100%)',
vintage: 'linear-gradient(to right, #d87c7c 0%, #919e8b 100%)',
chalk: 'linear-gradient(to right, #fc97af 0%, #87f7cf 100%)',
westeros: 'linear-gradient(to right, #516b91 0%, #edafda 100%)',
wonderland: 'linear-gradient(to right, #4ea397 0%, #22c3aa 100%)',
essos: 'linear-gradient(to right, #893448 0%, #d95850 100%)',
shine: 'linear-gradient(to right, #c12e34 0%, #0098d9 100%)',
roma: 'linear-gradient(to right, #e01f54 0%, #5e4ea5 100%)'
}
// 渐变主题色列表(主色1、主色2、阴影、渐变1、渐变2) // 渐变主题色列表(主色1、主色2、阴影、渐变1、渐变2)
export const chartColorsSearch = { export const chartColorsSearch = {
dark: ['#4992ff', '#7cffb2', 'rgba(68, 181, 226, 0.3)', 'rgba(73, 146, 255, 0.5)', 'rgba(124, 255, 178, 0.5)'], dark: ['#4992ff', '#7cffb2', 'rgba(68, 181, 226, 0.3)', 'rgba(73, 146, 255, 0.5)', 'rgba(124, 255, 178, 0.5)'],
+1 -1
View File
@@ -17,7 +17,7 @@
} }
@mixin deep() { @mixin deep() {
:deep(*) { :deep() {
@content; @content;
} }
} }
+10
View File
@@ -86,6 +86,16 @@ export function darken(color: string, concentration: number) {
return Color(color).darken(concentration).toString() return Color(color).darken(concentration).toString()
} }
/**
* hsl 转成16进制
* @param hsl
* @returns
*/
export function hslToHex(hslString: string): string {
const color = Color(hslString);
return color.hex()
}
/** /**
* * 修改主题色 * * 修改主题色
* @param themeName 主题名称 * @param themeName 主题名称
@@ -1,5 +1,14 @@
<template> <template>
<div class="go-chart-theme-color"> <div class="go-chart-theme-color">
<n-card class="card-box" size="small" hoverable embedded @click="createColorHandle">
<n-text class="go-flex-items-center">
<span>自定义颜色</span>
<n-icon size="16">
<add-icon></add-icon>
</n-icon>
</n-text>
</n-card>
<n-card <n-card
v-for="(value, key) in chartColors" v-for="(value, key) in chartColors"
:key="key" :key="key"
@@ -19,25 +28,36 @@
:style="{ backgroundColor: colorItem }" :style="{ backgroundColor: colorItem }"
></span> ></span>
</div> </div>
<div class="theme-bottom" :style="{ backgroundImage: chartColorsshow[key] }"></div> <div class="theme-bottom" :style="{ backgroundImage: colorBackgroundImage(value) }"></div>
</n-card> </n-card>
<!-- 自定义颜色 modal -->
<create-color v-model:modelShow="createColorModelShow"></create-color>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { ref, computed } from 'vue'
import cloneDeep from 'lodash/cloneDeep'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { chartColors, chartColorsName, chartColorsshow, ChartColorsNameType } from '@/settings/chartThemes/index' import { chartColors, chartColorsName, ChartColorsNameType } from '@/settings/chartThemes/index'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import cloneDeep from 'lodash/cloneDeep' import { loadAsyncComponent } from '@/utils'
import { icon } from '@/plugins' import { icon } from '@/plugins'
const { SquareIcon } = icon.ionicons5 const CreateColor = loadAsyncComponent(() => import('../CreateColor/index.vue'))
const { SquareIcon, AddIcon } = icon.ionicons5
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
// 全局颜色 // 全局颜色
const designStore = useDesignStore() const designStore = useDesignStore()
const createColorModelShow = ref(false)
// 创建颜色
const createColorHandle = () => {
createColorModelShow.value = true
}
// 颜色 // 颜色
const themeColor = computed(() => { const themeColor = computed(() => {
@@ -49,6 +69,11 @@ const selectName = computed(() => {
return chartEditStore.getEditCanvasConfig.chartThemeColor return chartEditStore.getEditCanvasConfig.chartThemeColor
}) })
// 底色
const colorBackgroundImage = (item: { color: string[] }) => {
return `linear-gradient(to right, ${item.color[0]} 0%, ${item.color[5]} 100%)`
}
// 获取用来展示的色号 // 获取用来展示的色号
const fetchShowColors = (colors: Array<string>) => { const fetchShowColors = (colors: Array<string>) => {
return cloneDeep(colors).splice(0, 6) return cloneDeep(colors).splice(0, 6)
@@ -62,9 +87,9 @@ const selectTheme = (theme: ChartColorsNameType) => {
<style lang="scss" scoped> <style lang="scss" scoped>
$radius: 10px; $radius: 10px;
$itemRadius: 6px;
@include go(chart-theme-color) { @include go('chart-theme-color') {
padding-top: 20px;
.card-box { .card-box {
cursor: pointer; cursor: pointer;
margin-top: 15px; margin-top: 15px;
@@ -72,12 +97,13 @@ $radius: 10px;
@include fetch-bg-color('background-color4-shallow'); @include fetch-bg-color('background-color4-shallow');
border-radius: $radius; border-radius: $radius;
overflow: hidden; overflow: hidden;
&.selected { &.selected {
border: 1px solid v-bind('themeColor'); border: 2px solid v-bind('themeColor');
border-bottom: 1px solid rgba(0, 0, 0, 0); border-bottom: 1px solid rgba(0, 0, 0, 0);
} }
&:first-child { &:first-child {
margin-top: 0; margin-top: 5px;
} }
.go-flex-items-center { .go-flex-items-center {
justify-content: space-between; justify-content: space-between;
@@ -87,7 +113,7 @@ $radius: 10px;
display: inline-block; display: inline-block;
width: 20px; width: 20px;
height: 20px; height: 20px;
border-radius: $radius; border-radius: $itemRadius;
} }
.theme-bottom { .theme-bottom {
position: absolute; position: absolute;
@@ -95,7 +121,6 @@ $radius: 10px;
bottom: 0px; bottom: 0px;
width: 100%; width: 100%;
height: 3px; height: 3px;
background-image: linear-gradient(to right, #e0c3fc 0%, #8ec5fc 100%);
} }
} }
} }
@@ -0,0 +1,331 @@
<template>
<n-modal class="go-chart-create-color" v-model:show="modelShowRef" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 900px; height: 720px">
<template #header></template>
<template #header-extra> </template>
<div class="create-content">
<div class="create-color-setting-box">
<create-color-render
v-if="selectColorId"
:selectColor="selectColor.selectInfo"
@updateColor="updateColorHandle"
></create-color-render>
<!-- 无数据 -->
<div v-else class="no-data go-flex-center">
<img :src="noData" alt="暂无数据" />
<n-text :depth="3">暂未选择自定义颜色</n-text>
</div>
</div>
<div class="color-list-box">
<n-timeline class="pond-item-timeline" style="width: 20px">
<n-timeline-item type="info"> </n-timeline-item>
<n-timeline-item type="success"></n-timeline-item>
</n-timeline>
<div class="color-list">
<n-space>
<!-- 新增 -->
<n-button
class="create-btn"
:class="{ 'is-full': !!!selectColorId }"
type="primary"
:ghost="!!!selectColorId"
:secondary="!!selectColorId"
@click="createColor"
>
<span> 创建 </span>
<template #icon>
<n-icon>
<duplicate-outline-icon></duplicate-outline-icon>
</n-icon>
</template>
</n-button>
<n-badge v-if="selectColorId" :show="updateColor !== undefined" dot>
<n-button class="create-btn" type="info" secondary @click="saveHandle">
<span> 应用数据 </span>
<template #icon>
<n-icon>
<arrow-down-icon></arrow-down-icon>
</n-icon>
</template>
</n-button>
</n-badge>
</n-space>
<n-divider style="margin: 10px 0"></n-divider>
<n-text v-if="!selectColorId" class="not-data-text" :depth="3">
暂无自定义颜色
<n-a @click="createColor">立即创建</n-a>
</n-text>
<!-- 列表 -->
<div class="color-card-box" v-for="(item, index) in colorList" :key="item.id">
<n-card
class="color-card"
:class="{ selected: item.id === selectColorId }"
size="small"
hoverable
embedded
@click="selectHandle(item)"
>
<div class="go-flex-items-center">
<n-ellipsis style="text-align: left; width: 70px">{{ item.name }} </n-ellipsis>
<span
class="theme-color-item"
v-for="colorItem in item.color"
:key="colorItem"
:style="{ backgroundColor: colorItem }"
></span>
</div>
<div class="theme-bottom" :style="{ backgroundImage: colorBackgroundImage(item) }"></div>
</n-card>
<n-tooltip trigger="hover">
<template #trigger>
<n-button text :disabled="item.id === selectColorId" @click="deleteHandle(index)">
<n-icon class="go-ml-1 go-cursor-pointer" size="16" :depth="3">
<trash-icon></trash-icon>
</n-icon>
</n-button>
</template>
删除自定义颜色
</n-tooltip>
</div>
</div>
</div>
</div>
<!-- 底部 -->
<template #action>
<n-space justify="end">
<n-button @click="closeHandle">操作完成</n-button>
</n-space>
</template>
</n-card>
</n-modal>
</template>
<script setup lang="ts">
import { ref, watch, computed, reactive } from 'vue'
import cloneDeep from 'lodash/cloneDeep'
import { CreateColorRender } from '../CreateColorRender/index'
import noData from '@/assets/images/canvas/noData.png'
import { getUUID, goDialog } from '@/utils'
import { icon } from '@/plugins'
import { UvIndex } from '@vicons/carbon'
const props = defineProps({
modelShow: Boolean
})
const emit = defineEmits(['update:modelShow', 'editSaveHandle'])
const { DuplicateOutlineIcon, TrashIcon, ArrowDownIcon } = icon.ionicons5
type ColorType = {
id: string
name: string
color: string[]
}
// 默认颜色组
const defaultColor: ColorType = {
id: getUUID(),
name: '未命名',
color: ['#6ae5bb', '#69e3de', '#5ac4ee', '#5ac4ee', '#4498ec', '#3c7ddf']
}
const modelShowRef = ref(false)
// 颜色列表
let colorList = reactive<Array<ColorType>>([])
// 子组件更新过的数据
const updateColor = ref<ColorType | undefined>(undefined)
// 所选颜色
const selectColor = reactive<{
selectInfo: ColorType | undefined
}>({
selectInfo: colorList[0]
})
watch(
() => props.modelShow,
newValue => {
modelShowRef.value = newValue
}
)
const selectColorId = computed(() => selectColor?.selectInfo?.id)
// 选择
const selectHandle = (item: ColorType) => {
if (item.id === selectColorId.value) return
if (updateColor.value !== undefined) {
goDialog({
message: '当前有变动未保存,是否直接放弃修改?',
onPositiveCallback: () => {
updateColor.value = undefined
selectColor.selectInfo = item
}
})
} else {
selectColor.selectInfo = item
}
}
// 创建
const createColor = () => {
const positiveHandle = () => {
const newData = { ...cloneDeep(defaultColor), id: getUUID() }
selectColor.selectInfo = newData
colorList.push(newData)
selectHandle(newData)
}
if (updateColor.value !== undefined) {
goDialog({
message: '当前有变动未保存,是否直接放弃修改?',
onPositiveCallback: () => {
updateColor.value = undefined
positiveHandle()
}
})
} else {
positiveHandle()
}
}
// 删除
const deleteHandle = (index: number) => {
colorList.splice(index, 1)
}
// 存储更新数据的值
const updateColorHandle = (newColor: ColorType) => {
updateColor.value = newColor
}
// 保存数据
const saveHandle = () => {
if (!updateColor.value) return
const index = colorList.findIndex(item => item.id === updateColor.value?.id)
if (index !== -1) {
colorList.splice(index, 1, cloneDeep(updateColor.value))
window.$message.success('颜色应用成功!')
updateColor.value = undefined
} else {
window.$message.error('颜色应用失败!')
}
}
// 取消
const closeHandle = () => {
colorList.splice(0, colorList.length)
selectColor.selectInfo = undefined
emit('update:modelShow', false)
}
// 底色
const colorBackgroundImage = (item: ColorType) => {
return `linear-gradient(to right, ${item.color[0]} 0%, ${item.color[5]} 100%)`
}
</script>
<style scoped lang="scss">
$height: 600px;
$listWidth: 280px;
$color-radius: 8px;
$color-item-radius: 4px;
@include go('chart-create-color') {
.create-content {
display: flex;
/* 左侧 */
.create-color-setting-box {
flex: 1;
.no-data {
flex-direction: column;
width: 100%;
height: 100%;
img {
width: 200px;
}
}
}
/* 列表 */
.color-list-box {
display: flex;
padding-top: 10px;
margin-right: 5px;
.pond-item-timeline > .n-timeline-item {
&:first-child {
height: $height;
}
}
.color-list {
width: $listWidth;
position: relative;
padding-right: 8px;
.create-btn {
width: 133px;
&.is-full {
width: 280px;
}
}
.not-data-text {
display: block;
text-align: center;
}
.color-card-box {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 15px;
&:first-child {
margin-top: 0;
}
.color-card {
overflow: hidden;
cursor: pointer;
border-radius: $color-radius;
border: 2px solid rgba(0, 0, 0, 0);
border-bottom: 1px solid rgba(0, 0, 0, 0);
@include fetch-bg-color('background-color4-shallow');
@include deep() {
& > .n-card__content {
padding: 7px;
padding-top: 10px;
padding-bottom: 10px;
}
}
&.selected {
border: 2px solid var(--n-color-target);
border-bottom: 1px solid rgba(0, 0, 0, 0);
}
.go-flex-items-center {
justify-content: space-between;
margin-top: -4px;
}
.theme-color-item {
display: inline-block;
width: 16px;
height: 16px;
border-radius: $color-item-radius;
}
.theme-bottom {
position: absolute;
left: 0;
bottom: 0px;
width: 100%;
height: 3px;
}
}
}
}
}
}
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important;
}
@include deep() {
& > .n-card__content {
padding-right: 0;
}
}
}
</style>
@@ -0,0 +1,3 @@
import CreateColorRender from './index.vue'
export { CreateColorRender }
@@ -0,0 +1,233 @@
<template>
<div class="create-color-setting" v-if="editColor">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true">
<n-space justify="space-between">
<!-- 名称 -->
<n-input-group>
<n-input-group-label>名称:</n-input-group-label>
<n-input class="create-color-name" v-model:value="editColor.name" @change="titleChangeHandle"/>
</n-input-group>
<n-tag type="warning">底部图表仅展示 7 条数据</n-tag>
</n-space>
<!-- 颜色 -->
<n-scrollbar style="max-height: 132px">
<div class="color-list-box go-mt-3" :x-gap="12" :y-gap="12" :cols="4">
<div class="color-list-item" v-for="(item, index) in editColor.color" :key="index">
<div class="go-flex-items-center" :class="{ select: index === targetColor.index }">
<n-color-picker
style="width: 95px"
v-model:value="editColor.color[index]"
:show-preview="true"
:modes="['hex']"
@complete="completeHandle($event, index)"
/>
<div v-show="index > 5">
<n-tooltip trigger="hover">
<template #trigger>
<n-icon class="go-ml-1 go-cursor-pointer" size="16" :depth="3" @click="deleteColor(index)">
<trash-icon></trash-icon>
</n-icon>
</template>
删除颜色
</n-tooltip>
</div>
</div>
</div>
<div>
<n-button type="primary" secondary @click="addColor">
<div class="go-flex-items-center">
<span class="go-mr-4">添加</span>
<n-icon size="16">
<add-icon></add-icon>
</n-icon>
</div>
</n-button>
</div>
</div>
</n-scrollbar>
</n-card>
<!-- 扩展色 -->
<n-card class="go-mt-3" :bordered="false" role="dialog" size="small" aria-modal="true">
<n-text>扩展色</n-text>
<n-divider style="margin: 10px 0"></n-divider>
<n-space :size="[4, 0]" justify="center">
<div
class="color-computed-item"
v-for="(item, index) in expandColorList"
:key="index"
@click="selectExpandColor(item)"
>
<div class="n-color-picker-checkboard"></div>
<div :style="getRenderBackgroundColor(item)"></div>
</div>
</n-space>
</n-card>
<!-- 展示图表 -->
<create-color-render-chart :color="cloneDeep(editColor.color).splice(0, 7)"></create-color-render-chart>
</div>
</template>
<script setup lang="ts">
import { PropType, ref, watch, computed, reactive, nextTick } from 'vue'
import cloneDeep from 'lodash/cloneDeep'
import { darken, lighten, fade, hslToHex, loadAsyncComponent } from '@/utils'
import { icon } from '@/plugins'
type ColorType = {
id: string
name: string
color: string[]
}
const props = defineProps({
selectColor: Object as PropType<ColorType>
})
const emit = defineEmits(['updateColor'])
const { AddIcon, TrashIcon } = icon.ionicons5
const CreateColorRenderChart = loadAsyncComponent(() => import('../CreateColorRenderChart/index.vue'))
// 拷贝的一份数据
const editColor = ref<ColorType | undefined>()
// 目标颜色
const targetColor = reactive<{
index: number
color?: string
}>({
// -1 表示无选中元素
index: -1,
color: ''
})
// 监听值
watch(
() => props.selectColor?.id,
() => {
editColor.value = cloneDeep(props.selectColor)
targetColor.index = 0
targetColor.color = editColor.value?.color[0]
},
{
immediate: true,
deep: false
}
)
// 扩展色
const expandColorList = computed(() => {
return computedColorList(targetColor.color)
})
// 计算背景色
const computedColorList = (color?: string) => {
if (!color) return []
const num: number = 20
const comDarkenArr: string[] = []
const comLightenArr: string[] = []
const comDarkenFadeArr: string[] = []
for (let i = 0; i < num; i++) {
comLightenArr.unshift(lighten(color, (2 / 100) * i))
comDarkenArr.push(darken(color, (3.5 / 100) * i))
}
// 透明
comDarkenArr.forEach((item, i) => {
comDarkenFadeArr.unshift(fade(item, (2.4 / 100) * i))
})
return [...comDarkenFadeArr, ...comLightenArr, ...comDarkenArr]
}
// 渲染背景色
const getRenderBackgroundColor = (color?: string) => {
return {
backgroundColor: color
}
}
// 顶部选择颜色
const completeHandle = (color?: string, index?: number) => {
color && (targetColor.color = color)
index && (targetColor.index = index)
nextTick(() => {
emit('updateColor', editColor.value)
})
}
// 选择扩展色
const selectExpandColor = (color: string) => {
const hexColor = hslToHex(color)
editColor.value && (editColor.value.color[targetColor.index] = hexColor)
nextTick(() => {
emit('updateColor', editColor.value)
})
}
// 新增颜色
const addColor = () => {
const lastData = editColor.value?.color[editColor.value?.color.length - 1] || '#2c2c31'
editColor.value?.color.push(lastData)
}
// 删除颜色
const deleteColor = (index: number) => {
editColor.value?.color.splice(index, 1)
if (index === targetColor.index) {
completeHandle(editColor.value?.color[index - 1], index - 1)
}
}
// 修改名称
const titleChangeHandle = () => {
nextTick(() => {
emit('updateColor', editColor.value)
})
}
</script>
<style scoped lang="scss">
.create-color-setting {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
padding-right: 10px;
.create-color-name {
width: 200px;
}
.color-list-box {
display: flex;
flex-wrap: wrap;
row-gap: 8px;
.color-list-item {
width: calc(100% / 4);
.select {
.n-color-picker {
border: 2px solid v-bind('targetColor.color');
border-radius: 5px;
}
}
}
}
.color-computed-item {
& div {
position: absolute;
display: inline-block;
height: 22px;
width: 22px;
}
position: relative;
display: inline-block;
height: 22px;
width: 22px;
cursor: pointer;
overflow: hidden;
border-radius: 4px;
}
}
</style>
@@ -0,0 +1,47 @@
import { echartOptionProfixHandle } from '@/packages/public'
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
const seriesHandle = (color: string[]) => {
const numHandle = (numsi: number, i: number) => parseInt(`${numsi * Math.random()}`, 10) * 2
const nums = [60, 51, 200, 334, 366, 456, 223]
return color.map((item, index) => ({
name: `data${index + 1}`,
type: 'bar',
data: nums.map((numsItem, numsi) => numHandle(numsItem, index))
}))
}
export const option = (color: string[]) => {
return echartOptionProfixHandle(
{
tooltip: {
trigger: 'axis',
showContent: false,
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: color.map((e, i) => `data${i + 1}`),
axisTick: {
alignWithLabel: true
}
},
yAxis: {
show: true,
type: 'value'
},
series: seriesHandle(color || [])
},
includes
)
}
@@ -0,0 +1,3 @@
import CreateColorRenderChart from './index.vue'
export { CreateColorRenderChart }
@@ -0,0 +1,69 @@
<template>
<n-space>
<n-card v-if="barOption" class="go-mt-3" :bordered="false" role="dialog" size="small" aria-modal="true">
<n-tabs type="segment" size="small" animated>
<n-tab-pane name="柱状图" tab="柱状图">
<v-chart
ref="vChartRefBar"
:theme="{ color }"
:option="barOption"
:manual-update="true"
autoresize
:style="chartStyle"
></v-chart>
</n-tab-pane>
<n-tab-pane name="折线图" tab="折线图">
<v-chart
ref="vChartRefLine"
:theme="{ color }"
:option="lineOption"
:manual-update="true"
autoresize
:style="chartStyle"
></v-chart>
</n-tab-pane>
</n-tabs>
</n-card>
</n-space>
</template>
<script setup lang="ts">
import { ref, watch, PropType } from 'vue'
import VChart from 'vue-echarts'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart, LineChart } from 'echarts/charts'
import { use } from 'echarts/core'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import { option as barOptions } from './barOptions'
import { option as lineOptions } from './lineOptions'
const props = defineProps({
color: {
type: Array as PropType<string[]>,
required: true
}
})
use([DatasetComponent, CanvasRenderer, BarChart, LineChart, GridComponent, TooltipComponent, LegendComponent])
const barOption = ref()
const lineOption = ref()
const chartStyle = {
width: '528px',
height: '200px'
}
watch(
() => props.color,
(newData: string[]) => {
barOption.value = barOptions(newData)
lineOption.value = lineOptions(newData)
},
{
immediate: true,
deep: true
}
)
</script>
<style lang="scss" scoped></style>
@@ -0,0 +1,72 @@
import { echartOptionProfixHandle } from '@/packages/public'
import { graphic } from 'echarts/core'
import { fade, hslToHex } from '@/utils'
export const includes = ['legend', 'xAxis', 'yAxis', 'grid']
const seriesHandle = (color: string[]) => {
const numHandle = (numsi: number, i: number) => parseInt(`${numsi * Math.random()}`, 10) * 2
const nums = [130, 251, 200, 334, 366, 456, 223]
return color.map((item, index) => ({
name: `data${index + 1}`,
type: 'line',
smooth: true,
lineStyle: {
width: 1,
type: 'solid'
},
emphasis: {
focus: 'series'
},
areaStyle: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 1,
color: item
},
{
offset: 0,
color: item
}
])
},
showSymbol: false,
data: nums.reverse().map((numsItem, numsi) => numHandle(numsItem, index))
}))
}
export const option = (color: string[]) => {
return echartOptionProfixHandle(
{
tooltip: {
trigger: 'axis',
showContent: false,
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: color.map((e, i) => `data${i + 1}`),
axisTick: {
alignWithLabel: true
}
},
yAxis: {
show: true,
type: 'value'
},
series: seriesHandle(color || [])
},
includes
)
}
@@ -128,6 +128,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick, watch } from 'vue' import { ref, nextTick, watch } from 'vue'
import { backgroundImageSize } from '@/settings/designSetting' import { backgroundImageSize } from '@/settings/designSetting'
import { swatchesColors } from '@/settings/chartThemes/index'
import { FileTypeEnum } from '@/enums/fileTypeEnum' import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
@@ -162,9 +163,6 @@ const selectColorOptions = [
} }
] ]
// 默认展示颜色列表
const swatchesColors = ['#232324', '#2a2a2b', '#313132', '#373739', '#757575', '#e0e0e0', '#eeeeee', '#fafafa']
const globalTabList = [ const globalTabList = [
{ {
key: 'ChartTheme', key: 'ChartTheme',