feat: 新增自定义颜色弹窗

This commit is contained in:
奔跑的面条 2023-02-25 22:00:55 +08:00
parent c74b3957a6
commit a8ac40770d
14 changed files with 817 additions and 30 deletions

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,
// 搜索(放大镜) // 搜索(放大镜)

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,

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)'],

View File

@ -17,7 +17,7 @@
} }
@mixin deep() { @mixin deep() {
:deep(*) { :deep() {
@content; @content;
} }
} }

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

View File

@ -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%);
} }
} }
} }

View File

@ -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>

View File

@ -0,0 +1,3 @@
import CreateColorRender from './index.vue'
export { CreateColorRender }

View File

@ -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>

View File

@ -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
)
}

View File

@ -0,0 +1,3 @@
import CreateColorRenderChart from './index.vue'
export { CreateColorRenderChart }

View File

@ -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>

View File

@ -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
)
}

View File

@ -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',