Showing
45 changed files
with
376 additions
and
2050 deletions
src/api/external/contentSave/content.ts
0 → 100644
1 | +import { defHttp } from '@/utils/external/http/axios'; | |
2 | +import { | |
3 | + ContentParams, | |
4 | + LoginResultModel, | |
5 | +} from './model/userModel'; | |
6 | + | |
7 | +import type { ErrorMessageMode } from '/#/external/axios'; | |
8 | + | |
9 | +enum Api { | |
10 | + CONTENT = '/data_view/content', | |
11 | +} | |
12 | + | |
13 | +/** | |
14 | + * @description: content save api | |
15 | + */ | |
16 | +export function contentSaveApi(params: ContentParams, mode: ErrorMessageMode = 'modal') { | |
17 | + return defHttp.post<LoginResultModel>( | |
18 | + { | |
19 | + url: Api.CONTENT, | |
20 | + params, | |
21 | + }, | |
22 | + { | |
23 | + errorMessageMode: mode, | |
24 | + } | |
25 | + ); | |
26 | +} | ... | ... |
1 | +/** | |
2 | + * @description: Login interface parameters | |
3 | + */ | |
4 | +export interface ContentParams{ | |
5 | + "content": string, | |
6 | + "createTime": string, | |
7 | + "creator": string, | |
8 | + "defaultConfig": string, | |
9 | + "description": string, | |
10 | + "enabled": boolean, | |
11 | + "icon": string, | |
12 | + "id": string, | |
13 | + "name": string, | |
14 | + "nodeIds": [ | |
15 | + string | |
16 | + ], | |
17 | + "remark": string, | |
18 | + "roleIds": [ | |
19 | + string | |
20 | + ], | |
21 | + "tenantExpireTime": string, | |
22 | + "tenantId": string, | |
23 | + "tenantProfileId": string, | |
24 | + "tenantStatus": string, | |
25 | + "updateTime":string, | |
26 | + "updater":string, | |
27 | + "viewId":string | |
28 | +} | |
29 | +export interface RoleInfo { | |
30 | + roleName: string; | |
31 | + value: string; | |
32 | +} | |
33 | + | |
34 | +/** | |
35 | + * @description: Login interface return value | |
36 | + */ | |
37 | +export interface LoginResultModel {{ | |
38 | + "content": string, | |
39 | + "createTime": string, | |
40 | + "creator": string, | |
41 | + "defaultConfig": string, | |
42 | + "description": string, | |
43 | + "enabled": boolean, | |
44 | + "icon": string, | |
45 | + "id": string, | |
46 | + "name": string, | |
47 | + "nodeIds": [ | |
48 | + string | |
49 | + ], | |
50 | + "remark": string, | |
51 | + "roleIds": [ | |
52 | + string | |
53 | + ], | |
54 | + "tenantExpireTime": string, | |
55 | + "tenantId": string, | |
56 | + "tenantProfileId": string, | |
57 | + "tenantStatus": string, | |
58 | + "updateTime":string, | |
59 | + "updater":string, | |
60 | + "viewId":string | |
61 | +} | |
62 | + | ... | ... |
src/packages/components/Artoons/Mores/WordCloud/config.ts
deleted
100644 → 0
1 | -import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public' | |
2 | -import { WordCloudConfig } from './index' | |
3 | -import { CreateComponentType } from '@/packages/index.d' | |
4 | -import cloneDeep from 'lodash/cloneDeep' | |
5 | -import dataJson from './data.json' | |
6 | - | |
7 | -export const includes = [] | |
8 | - | |
9 | -export const ShapeEnumList = [ | |
10 | - { label: '圆形', value: 'circle' }, | |
11 | - { label: '心形', value: 'cardioid' }, | |
12 | - { label: '钻石', value: 'diamond' }, | |
13 | - { label: '右三角形', value: 'triangle-forward' }, | |
14 | - { label: '三角形', value: 'triangle' }, | |
15 | - { label: '五边形', value: 'pentagon' }, | |
16 | - { label: '星星', value: 'star' } | |
17 | -] | |
18 | - | |
19 | -export const option = { | |
20 | - dataset: [...dataJson], | |
21 | - tooltip: {}, | |
22 | - series: [ | |
23 | - { | |
24 | - type: 'wordCloud', | |
25 | - | |
26 | - // “云”绘制的形状,可以是表示为回调函数,也可以是固定关键字。 | |
27 | - // 可用值有:circle|cardioid|diamond|triangle-forward|triangle|pentagon|star | |
28 | - shape: 'circle', | |
29 | - | |
30 | - // 白色区域将被排除在绘制文本之外的剪影图像。 | |
31 | - // 随着云的形状生长,形状选项将继续应用。 | |
32 | - // maskImage: maskImage, | |
33 | - | |
34 | - // Folllowing left/top/width/height/right/bottom are used for positioning the word cloud | |
35 | - // Default to be put in the center and has 75% x 80% size. | |
36 | - left: 'center', | |
37 | - top: 'center', | |
38 | - width: '70%', | |
39 | - height: '80%', | |
40 | - right: null, | |
41 | - bottom: null, | |
42 | - | |
43 | - // 文本大小范围,默认 [12,60] | |
44 | - sizeRange: [12, 60], | |
45 | - | |
46 | - // 文本旋转范围和程度的步骤。 文本将通过旋转步骤45在[-90,90]中随机旋转 | |
47 | - rotationRange: [0, 0], | |
48 | - rotationStep: 0, | |
49 | - | |
50 | - // size of the grid in pixels for marking the availability of the canvas | |
51 | - // 网格大小越大,单词之间的差距就越大。 | |
52 | - gridSize: 8, | |
53 | - | |
54 | - // 设置为true,以允许单词在画布之外部分地绘制。允许绘制大于画布的大小 | |
55 | - drawOutOfBound: false, | |
56 | - | |
57 | - // If perform layout animation. | |
58 | - // NOTE disable it will lead to UI blocking when there is lots of words. | |
59 | - layoutAnimation: true, | |
60 | - | |
61 | - // Global text style | |
62 | - textStyle: { | |
63 | - fontFamily: 'sans-serif', | |
64 | - fontWeight: 'bold' | |
65 | - // 颜色可以是回调功能或颜色字符串 | |
66 | - // color: function () { | |
67 | - // // 随机颜色 | |
68 | - // return ( | |
69 | - // 'rgb(' + | |
70 | - // [Math.round(Math.random() * 160), Math.round(Math.random() * 160), Math.round(Math.random() * 160)].join( | |
71 | - // ',' | |
72 | - // ) + | |
73 | - // ')' | |
74 | - // ) | |
75 | - // } | |
76 | - }, | |
77 | - emphasis: { | |
78 | - focus: 'self', | |
79 | - | |
80 | - textStyle: { | |
81 | - shadowBlur: 10, | |
82 | - shadowColor: '#333' | |
83 | - } | |
84 | - }, | |
85 | - data: [...dataJson] | |
86 | - } | |
87 | - ] | |
88 | -} | |
89 | - | |
90 | -export default class Config extends PublicConfigClass implements CreateComponentType { | |
91 | - public key = WordCloudConfig.key | |
92 | - public chartConfig = cloneDeep(WordCloudConfig) | |
93 | - // 图表配置项 | |
94 | - public option = echartOptionProfixHandle(option, includes) | |
95 | -} |
src/packages/components/Artoons/Mores/WordCloud/config.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <collapse-item name="词云" expanded> | |
3 | - <setting-item-box name="形状"> | |
4 | - <setting-item> | |
5 | - <n-select v-model:value="optionData.series[0].shape" size="small" :options="ShapeEnumList" /> | |
6 | - </setting-item> | |
7 | - <setting-item> | |
8 | - <n-checkbox v-model:checked="optionData.series[0].drawOutOfBound" size="small">允许出边</n-checkbox> | |
9 | - </setting-item> | |
10 | - </setting-item-box> | |
11 | - | |
12 | - <setting-item-box name="布局"> | |
13 | - <setting-item name="宽度"> | |
14 | - <n-slider | |
15 | - v-model:value="series.width" | |
16 | - :min="0" | |
17 | - :max="100" | |
18 | - :format-tooltip="sliderFormatTooltip" | |
19 | - @update:value="updateWidth" | |
20 | - ></n-slider> | |
21 | - </setting-item> | |
22 | - <setting-item name="高度"> | |
23 | - <n-slider | |
24 | - v-model:value="series.height" | |
25 | - :min="0" | |
26 | - :max="100" | |
27 | - :format-tooltip="sliderFormatTooltip" | |
28 | - @update:value="updateHeight" | |
29 | - ></n-slider> | |
30 | - </setting-item> | |
31 | - </setting-item-box> | |
32 | - | |
33 | - <setting-item-box name="样式" alone> | |
34 | - <setting-item name="字体区间(最小/最大字体)"> | |
35 | - <n-slider v-model:value="optionData.series[0].sizeRange" range :step="1" :min="6" :max="100" /> | |
36 | - </setting-item> | |
37 | - <setting-item name="旋转角度"> | |
38 | - <n-slider v-model:value="series.rotationStep" :step="15" :min="0" :max="45" @update:value="updateRotation" /> | |
39 | - </setting-item> | |
40 | - </setting-item-box> | |
41 | - </collapse-item> | |
42 | -</template> | |
43 | - | |
44 | -<script setup lang="ts"> | |
45 | -import { PropType, computed } from 'vue' | |
46 | -import { option, ShapeEnumList } from './config' | |
47 | -// eslint-disable-next-line no-unused-vars | |
48 | -import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' | |
49 | - | |
50 | -const props = defineProps({ | |
51 | - optionData: { | |
52 | - type: Object as PropType<typeof option>, | |
53 | - required: true | |
54 | - } | |
55 | -}) | |
56 | - | |
57 | -const series = computed(() => { | |
58 | - const { width, height, rotationStep } = props.optionData.series[0] | |
59 | - return { | |
60 | - width: +width.replace('%', ''), | |
61 | - height: +height.replace('%', ''), | |
62 | - rotationStep | |
63 | - } | |
64 | -}) | |
65 | - | |
66 | -const sliderFormatTooltip = (v: number) => { | |
67 | - return `${v}%` | |
68 | -} | |
69 | - | |
70 | -const updateWidth = (value: number) => { | |
71 | - props.optionData.series[0].width = `${value}%` | |
72 | -} | |
73 | - | |
74 | -const updateHeight = (value: number) => { | |
75 | - props.optionData.series[0].height = `${value}%` | |
76 | -} | |
77 | - | |
78 | -const updateRotation = (value: number) => { | |
79 | - props.optionData.series[0].rotationStep = value | |
80 | - props.optionData.series[0].rotationRange = value === 0 ? [0, 0] : [-90, 90] | |
81 | -} | |
82 | -</script> |
src/packages/components/Artoons/Mores/WordCloud/data.json
deleted
100644 → 0
1 | -[ | |
2 | - { | |
3 | - "name": "数据可视化", | |
4 | - "value": 8000, | |
5 | - "textStyle": { | |
6 | - "color": "#78fbb2" | |
7 | - }, | |
8 | - "emphasis": { | |
9 | - "textStyle": { | |
10 | - "color": "red" | |
11 | - } | |
12 | - } | |
13 | - }, | |
14 | - { | |
15 | - "name": "GO VIEW", | |
16 | - "value": 6181 | |
17 | - }, | |
18 | - { | |
19 | - "name": "低代码", | |
20 | - "value": 4386 | |
21 | - }, | |
22 | - { | |
23 | - "name": "Vue3", | |
24 | - "value": 4055 | |
25 | - }, | |
26 | - { | |
27 | - "name": "TypeScript4", | |
28 | - "value": 2467 | |
29 | - }, | |
30 | - { | |
31 | - "name": "Vite2", | |
32 | - "value": 2244 | |
33 | - }, | |
34 | - { | |
35 | - "name": "NaiveUI", | |
36 | - "value": 1898 | |
37 | - }, | |
38 | - { | |
39 | - "name": "ECharts5", | |
40 | - "value": 1484 | |
41 | - }, | |
42 | - { | |
43 | - "name": "Axios", | |
44 | - "value": 1112 | |
45 | - }, | |
46 | - { | |
47 | - "name": "Pinia2", | |
48 | - "value": 965 | |
49 | - }, | |
50 | - { | |
51 | - "name": "PlopJS", | |
52 | - "value": 847 | |
53 | - }, | |
54 | - { | |
55 | - "name": "sfc", | |
56 | - "value": 582 | |
57 | - }, | |
58 | - { | |
59 | - "name": "SCSS", | |
60 | - "value": 555 | |
61 | - }, | |
62 | - { | |
63 | - "name": "pnpm", | |
64 | - "value": 550 | |
65 | - }, | |
66 | - { | |
67 | - "name": "eslint", | |
68 | - "value": 462 | |
69 | - }, | |
70 | - { | |
71 | - "name": "json", | |
72 | - "value": 366 | |
73 | - }, | |
74 | - { | |
75 | - "name": "图表", | |
76 | - "value": 360 | |
77 | - }, | |
78 | - { | |
79 | - "name": "地图", | |
80 | - "value": 282 | |
81 | - }, | |
82 | - { | |
83 | - "name": "时钟", | |
84 | - "value": 273 | |
85 | - }, | |
86 | - { | |
87 | - "name": "标题", | |
88 | - "value": 265 | |
89 | - } | |
90 | -] |
src/packages/components/Artoons/Mores/WordCloud/index.ts
deleted
100644 → 0
1 | -import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d' | |
2 | -import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d' | |
3 | - | |
4 | -export const WordCloudConfig: ConfigType = { | |
5 | - key: 'WordCloud', | |
6 | - chartKey: 'VWordCloud', | |
7 | - conKey: 'VCWordCloud', | |
8 | - title: '词云', | |
9 | - category: ChatCategoryEnum.MORE, | |
10 | - categoryName: ChatCategoryEnumName.MORE, | |
11 | - package: PackagesCategoryEnum.INFORMATIONS, | |
12 | - chartFrame: ChartFrameEnum.COMMON, | |
13 | - image: 'words_cloud.png' | |
14 | -} |
src/packages/components/Artoons/Mores/WordCloud/index.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <v-chart | |
3 | - ref="vChartRef" | |
4 | - :theme="themeColor" | |
5 | - :option="option" | |
6 | - :manual-update="isPreview()" | |
7 | - :update-options="{ replaceMerge: replaceMergeArr }" | |
8 | - autoresize | |
9 | - ></v-chart> | |
10 | -</template> | |
11 | - | |
12 | -<script setup lang="ts"> | |
13 | -import { ref, computed, watch, PropType } from 'vue' | |
14 | -import VChart from 'vue-echarts' | |
15 | -import 'echarts-wordcloud' | |
16 | -import { use } from 'echarts/core' | |
17 | -import { CanvasRenderer } from 'echarts/renderers' | |
18 | -import config, { includes } from './config' | |
19 | -import { mergeTheme, setOption } from '@/packages/public/chart' | |
20 | -import { useChartDataFetch } from '@/hooks' | |
21 | -import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
22 | -import { isPreview } from '@/utils' | |
23 | -import { GridComponent, TooltipComponent } from 'echarts/components' | |
24 | -import dataJson from './data.json' | |
25 | - | |
26 | -const props = defineProps({ | |
27 | - themeSetting: { | |
28 | - type: Object, | |
29 | - required: true | |
30 | - }, | |
31 | - themeColor: { | |
32 | - type: Object, | |
33 | - required: true | |
34 | - }, | |
35 | - chartConfig: { | |
36 | - type: Object as PropType<config>, | |
37 | - required: true | |
38 | - } | |
39 | -}) | |
40 | - | |
41 | -use([CanvasRenderer, GridComponent, TooltipComponent]) | |
42 | - | |
43 | -const replaceMergeArr = ref<string[]>() | |
44 | - | |
45 | -const option = computed(() => { | |
46 | - return mergeTheme(props.chartConfig.option, props.themeSetting, includes) | |
47 | -}) | |
48 | - | |
49 | -const dataSetHandle = (dataset: typeof dataJson) => { | |
50 | - try { | |
51 | - dataset && (props.chartConfig.option.series[0].data = dataset) | |
52 | - vChartRef.value && isPreview() && setOption(vChartRef.value, props.chartConfig.option) | |
53 | - } catch (error) { | |
54 | - console.log(error) | |
55 | - } | |
56 | -} | |
57 | - | |
58 | -// dataset 无法变更条数的补丁 | |
59 | -watch( | |
60 | - () => props.chartConfig.option.dataset, | |
61 | - newData => { | |
62 | - dataSetHandle(newData) | |
63 | - }, | |
64 | - { | |
65 | - deep: false | |
66 | - } | |
67 | -) | |
68 | - | |
69 | -const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: typeof dataJson) => { | |
70 | - dataSetHandle(newData) | |
71 | -}) | |
72 | -</script> |
src/packages/components/Artoons/Mores/index.ts
deleted
100644 → 0
1 | -// eslint-disable-next-line @typescript-eslint/ban-ts-comment | |
2 | -// @ts-nocheck | |
3 | -import { | |
4 | - ArcCurve, | |
5 | - BufferAttribute, | |
6 | - BufferGeometry, | |
7 | - Color, | |
8 | - Line, | |
9 | - LineBasicMaterial, | |
10 | - Points, | |
11 | - PointsMaterial, | |
12 | - Quaternion, | |
13 | - Vector3 | |
14 | -} from 'three' | |
15 | -import { lon2xyz } from './common' | |
16 | - | |
17 | -/* | |
18 | - * 绘制一条圆弧飞线 | |
19 | - * 5个参数含义:( 飞线圆弧轨迹半径, 开始角度, 结束角度) | |
20 | - */ | |
21 | -function createFlyLine(radius, startAngle, endAngle, color) { | |
22 | - const geometry = new BufferGeometry() //声明一个几何体对象BufferGeometry | |
23 | - // ArcCurve创建圆弧曲线 | |
24 | - const arc = new ArcCurve(0, 0, radius, startAngle, endAngle, false) | |
25 | - //getSpacedPoints是基类Curve的方法,返回一个vector2对象作为元素组成的数组 | |
26 | - const pointsArr = arc.getSpacedPoints(100) //分段数80,返回81个顶点 | |
27 | - geometry.setFromPoints(pointsArr) // setFromPoints方法从pointsArr中提取数据改变几何体的顶点属性vertices | |
28 | - // 每个顶点对应一个百分比数据attributes.percent 用于控制点的渲染大小 | |
29 | - const percentArr = [] //attributes.percent的数据 | |
30 | - for (let i = 0; i < pointsArr.length; i++) { | |
31 | - percentArr.push(i / pointsArr.length) | |
32 | - } | |
33 | - const percentAttribue = new BufferAttribute(new Float32Array(percentArr), 1) | |
34 | - // 通过顶点数据percent点模型从大到小变化,产生小蝌蚪形状飞线 | |
35 | - geometry.attributes.percent = percentAttribue | |
36 | - // 批量计算所有顶点颜色数据 | |
37 | - const colorArr = [] | |
38 | - for (let i = 0; i < pointsArr.length; i++) { | |
39 | - const color1 = new Color(0xec8f43) //轨迹线颜色 青色 | |
40 | - const color2 = new Color(0xf3ae76) //黄色 | |
41 | - const color = color1.lerp(color2, i / pointsArr.length) | |
42 | - colorArr.push(color.r, color.g, color.b) | |
43 | - } | |
44 | - // 设置几何体顶点颜色数据 | |
45 | - geometry.attributes.color = new BufferAttribute(new Float32Array(colorArr), 3) | |
46 | - const size = 1.3 | |
47 | - // 点模型渲染几何体每个顶点 | |
48 | - const material = new PointsMaterial({ | |
49 | - size, //点大小 | |
50 | - // vertexColors: VertexColors, //使用顶点颜色渲染 | |
51 | - transparent: true, | |
52 | - depthWrite: false | |
53 | - }) | |
54 | - // 修改点材质的着色器源码(注意:不同版本细节可能会稍微会有区别,不过整体思路是一样的) | |
55 | - material.onBeforeCompile = function (shader) { | |
56 | - // 顶点着色器中声明一个attribute变量:百分比 | |
57 | - shader.vertexShader = shader.vertexShader.replace( | |
58 | - 'void main() {', | |
59 | - [ | |
60 | - 'attribute float percent;', //顶点大小百分比变量,控制点渲染大小 | |
61 | - 'void main() {' | |
62 | - ].join('\n') // .join()把数组元素合成字符串 | |
63 | - ) | |
64 | - // 调整点渲染大小计算方式 | |
65 | - shader.vertexShader = shader.vertexShader.replace( | |
66 | - 'gl_PointSize = size;', | |
67 | - ['gl_PointSize = percent * size;'].join('\n') // .join()把数组元素合成字符串 | |
68 | - ) | |
69 | - } | |
70 | - const FlyLine = new Points(geometry, material) | |
71 | - material.color = new Color(color) | |
72 | - FlyLine.name = '飞行线' | |
73 | - | |
74 | - return FlyLine | |
75 | -} | |
76 | - | |
77 | -/**输入地球上任意两点的经纬度坐标,通过函数flyArc可以绘制一个飞线圆弧轨迹 | |
78 | - * lon1,lat1:轨迹线起点经纬度坐标 | |
79 | - * lon2,lat2:轨迹线结束点经纬度坐标 | |
80 | - */ | |
81 | -function flyArc(radius, lon1, lat1, lon2, lat2, options) { | |
82 | - const sphereCoord1 = lon2xyz(radius, lon1, lat1) //经纬度坐标转球面坐标 | |
83 | - // startSphereCoord:轨迹线起点球面坐标 | |
84 | - const startSphereCoord = new Vector3(sphereCoord1.x, sphereCoord1.y, sphereCoord1.z) | |
85 | - const sphereCoord2 = lon2xyz(radius, lon2, lat2) | |
86 | - // startSphereCoord:轨迹线结束点球面坐标 | |
87 | - const endSphereCoord = new Vector3(sphereCoord2.x, sphereCoord2.y, sphereCoord2.z) | |
88 | - | |
89 | - //计算绘制圆弧需要的关于y轴对称的起点、结束点和旋转四元数 | |
90 | - const startEndQua = _3Dto2D(startSphereCoord, endSphereCoord) | |
91 | - // 调用arcXOY函数绘制一条圆弧飞线轨迹 | |
92 | - const arcline = arcXOY(radius, startEndQua.startPoint, startEndQua.endPoint, options) | |
93 | - arcline.quaternion.multiply(startEndQua.quaternion) | |
94 | - return arcline | |
95 | -} | |
96 | -/* | |
97 | - * 把3D球面上任意的两个飞线起点和结束点绕球心旋转到到XOY平面上, | |
98 | - * 同时保持关于y轴对称,借助旋转得到的新起点和新结束点绘制 | |
99 | - * 一个圆弧,最后把绘制的圆弧反向旋转到原来的起点和结束点即可 | |
100 | - */ | |
101 | -function _3Dto2D(startSphere, endSphere) { | |
102 | - /*计算第一次旋转的四元数:表示从一个平面如何旋转到另一个平面*/ | |
103 | - const origin = new Vector3(0, 0, 0) //球心坐标 | |
104 | - const startDir = startSphere.clone().sub(origin) //飞线起点与球心构成方向向量 | |
105 | - const endDir = endSphere.clone().sub(origin) //飞线结束点与球心构成方向向量 | |
106 | - // dir1和dir2构成一个三角形,.cross()叉乘计算该三角形法线normal | |
107 | - const normal = startDir.clone().cross(endDir).normalize() | |
108 | - const xoyNormal = new Vector3(0, 0, 1) //XOY平面的法线 | |
109 | - //.setFromUnitVectors()计算从normal向量旋转达到xoyNormal向量所需要的四元数 | |
110 | - // quaternion表示把球面飞线旋转到XOY平面上需要的四元数 | |
111 | - const quaternion3D_XOY = new Quaternion().setFromUnitVectors(normal, xoyNormal) | |
112 | - /*第一次旋转:飞线起点、结束点从3D空间第一次旋转到XOY平面*/ | |
113 | - const startSphereXOY = startSphere.clone().applyQuaternion(quaternion3D_XOY) | |
114 | - const endSphereXOY = endSphere.clone().applyQuaternion(quaternion3D_XOY) | |
115 | - | |
116 | - /*计算第二次旋转的四元数*/ | |
117 | - // middleV3:startSphereXOY和endSphereXOY的中点 | |
118 | - const middleV3 = startSphereXOY.clone().add(endSphereXOY).multiplyScalar(0.5) | |
119 | - const midDir = middleV3.clone().sub(origin).normalize() // 旋转前向量midDir,中点middleV3和球心构成的方向向量 | |
120 | - const yDir = new Vector3(0, 1, 0) // 旋转后向量yDir,即y轴 | |
121 | - // .setFromUnitVectors()计算从midDir向量旋转达到yDir向量所需要的四元数 | |
122 | - // quaternion2表示让第一次旋转到XOY平面的起点和结束点关于y轴对称需要的四元数 | |
123 | - const quaternionXOY_Y = new Quaternion().setFromUnitVectors(midDir, yDir) | |
124 | - | |
125 | - /*第二次旋转:使旋转到XOY平面的点再次旋转,实现关于Y轴对称*/ | |
126 | - const startSpherXOY_Y = startSphereXOY.clone().applyQuaternion(quaternionXOY_Y) | |
127 | - const endSphereXOY_Y = endSphereXOY.clone().applyQuaternion(quaternionXOY_Y) | |
128 | - | |
129 | - /**一个四元数表示一个旋转过程 | |
130 | - *.invert()方法表示四元数的逆,简单说就是把旋转过程倒过来 | |
131 | - * 两次旋转的四元数执行.invert()求逆,然后执行.multiply()相乘 | |
132 | - *新版本.invert()对应旧版本.invert() | |
133 | - */ | |
134 | - const quaternionInverse = quaternion3D_XOY.clone().invert().multiply(quaternionXOY_Y.clone().invert()) | |
135 | - return { | |
136 | - // 返回两次旋转四元数的逆四元数 | |
137 | - quaternion: quaternionInverse, | |
138 | - // 范围两次旋转后在XOY平面上关于y轴对称的圆弧起点和结束点坐标 | |
139 | - startPoint: startSpherXOY_Y, | |
140 | - endPoint: endSphereXOY_Y | |
141 | - } | |
142 | -} | |
143 | -/**通过函数arcXOY()可以在XOY平面上绘制一个关于y轴对称的圆弧曲线 | |
144 | - * startPoint, endPoint:表示圆弧曲线的起点和结束点坐标值,起点和结束点关于y轴对称 | |
145 | - * 同时在圆弧轨迹的基础上绘制一段飞线*/ | |
146 | -function arcXOY(radius, startPoint, endPoint, options) { | |
147 | - // 计算两点的中点 | |
148 | - const middleV3 = new Vector3().addVectors(startPoint, endPoint).multiplyScalar(0.5) | |
149 | - // 弦垂线的方向dir(弦的中点和圆心构成的向量) | |
150 | - const dir = middleV3.clone().normalize() | |
151 | - // 计算球面飞线的起点、结束点和球心构成夹角的弧度值 | |
152 | - const earthRadianAngle = radianAOB(startPoint, endPoint, new Vector3(0, 0, 0)) | |
153 | - /*设置飞线轨迹圆弧的中间点坐标 | |
154 | - 弧度值 * radius * 0.2:表示飞线轨迹圆弧顶部距离地球球面的距离 | |
155 | - 起点、结束点相聚越远,构成的弧线顶部距离球面越高*/ | |
156 | - const arcTopCoord = dir.multiplyScalar(radius + earthRadianAngle * radius * 0.2) // 黄色飞行线的高度 | |
157 | - //求三个点的外接圆圆心(飞线圆弧轨迹的圆心坐标) | |
158 | - const flyArcCenter = threePointCenter(startPoint, endPoint, arcTopCoord) | |
159 | - // 飞线圆弧轨迹半径flyArcR | |
160 | - const flyArcR = Math.abs(flyArcCenter.y - arcTopCoord.y) | |
161 | - /*坐标原点和飞线起点构成直线和y轴负半轴夹角弧度值 | |
162 | - 参数分别是:飞线圆弧起点、y轴负半轴上一点、飞线圆弧圆心*/ | |
163 | - const flyRadianAngle = radianAOB(startPoint, new Vector3(0, -1, 0), flyArcCenter) | |
164 | - const startAngle = -Math.PI / 2 + flyRadianAngle //飞线圆弧开始角度 | |
165 | - const endAngle = Math.PI - startAngle //飞线圆弧结束角度 | |
166 | - // 调用圆弧线模型的绘制函数 | |
167 | - const arcline = circleLine(flyArcCenter.x, flyArcCenter.y, flyArcR, startAngle, endAngle, options.color) | |
168 | - // const arcline = new Group();// 不绘制轨迹线,使用 Group替换circleLine()即可 | |
169 | - arcline.center = flyArcCenter //飞线圆弧自定一个属性表示飞线圆弧的圆心 | |
170 | - arcline.topCoord = arcTopCoord //飞线圆弧自定一个属性表示飞线圆弧中间也就是顶部坐标 | |
171 | - | |
172 | - // const flyAngle = Math.PI/ 10; //飞线圆弧固定弧度 | |
173 | - const flyAngle = (endAngle - startAngle) / 7 //飞线圆弧的弧度和轨迹线弧度相关 | |
174 | - // 绘制一段飞线,圆心做坐标原点 | |
175 | - const flyLine = createFlyLine(flyArcR, startAngle, startAngle + flyAngle, options.flyLineColor) | |
176 | - flyLine.position.y = flyArcCenter.y //平移飞线圆弧和飞线轨迹圆弧重合 | |
177 | - //飞线段flyLine作为飞线轨迹arcLine子对象,继承飞线轨迹平移旋转等变换 | |
178 | - arcline.add(flyLine) | |
179 | - //飞线段运动范围startAngle~flyEndAngle | |
180 | - flyLine.flyEndAngle = endAngle - startAngle - flyAngle | |
181 | - flyLine.startAngle = startAngle | |
182 | - // arcline.flyEndAngle:飞线段当前角度位置,这里设置了一个随机值用于演示 | |
183 | - flyLine.AngleZ = arcline.flyEndAngle * Math.random() | |
184 | - // flyLine.rotation.z = arcline.AngleZ; | |
185 | - // arcline.flyLine指向飞线段,便于设置动画是访问飞线段 | |
186 | - arcline.userData['flyLine'] = flyLine | |
187 | - | |
188 | - return arcline | |
189 | -} | |
190 | -/*计算球面上两点和球心构成夹角的弧度值 | |
191 | -参数point1, point2:表示地球球面上两点坐标Vector3 | |
192 | -计算A、B两点和顶点O构成的AOB夹角弧度值*/ | |
193 | -function radianAOB(A, B, O) { | |
194 | - // dir1、dir2:球面上两个点和球心构成的方向向量 | |
195 | - const dir1 = A.clone().sub(O).normalize() | |
196 | - const dir2 = B.clone().sub(O).normalize() | |
197 | - //点乘.dot()计算夹角余弦值 | |
198 | - const cosAngle = dir1.clone().dot(dir2) | |
199 | - const radianAngle = Math.acos(cosAngle) //余弦值转夹角弧度值,通过余弦值可以计算夹角范围是0~180度 | |
200 | - return radianAngle | |
201 | -} | |
202 | -/*绘制一条圆弧曲线模型Line | |
203 | -5个参数含义:(圆心横坐标, 圆心纵坐标, 飞线圆弧轨迹半径, 开始角度, 结束角度)*/ | |
204 | -function circleLine(x, y, r, startAngle, endAngle, color) { | |
205 | - const geometry = new BufferGeometry() //声明一个几何体对象Geometry | |
206 | - // ArcCurve创建圆弧曲线 | |
207 | - const arc = new ArcCurve(x, y, r, startAngle, endAngle, false) | |
208 | - //getSpacedPoints是基类Curve的方法,返回一个vector2对象作为元素组成的数组 | |
209 | - const points = arc.getSpacedPoints(80) //分段数50,返回51个顶点 | |
210 | - geometry.setFromPoints(points) // setFromPoints方法从points中提取数据改变几何体的顶点属性vertices | |
211 | - const material = new LineBasicMaterial({ | |
212 | - color: color || 0xd18547 | |
213 | - }) //线条材质 | |
214 | - const line = new Line(geometry, material) //线条模型对象 | |
215 | - return line | |
216 | -} | |
217 | -//求三个点的外接圆圆心,p1, p2, p3表示三个点的坐标Vector3。 | |
218 | -function threePointCenter(p1, p2, p3) { | |
219 | - const L1 = p1.lengthSq() //p1到坐标原点距离的平方 | |
220 | - const L2 = p2.lengthSq() | |
221 | - const L3 = p3.lengthSq() | |
222 | - const x1 = p1.x, | |
223 | - y1 = p1.y, | |
224 | - x2 = p2.x, | |
225 | - y2 = p2.y, | |
226 | - x3 = p3.x, | |
227 | - y3 = p3.y | |
228 | - const S = x1 * y2 + x2 * y3 + x3 * y1 - x1 * y3 - x2 * y1 - x3 * y2 | |
229 | - const x = (L2 * y3 + L1 * y2 + L3 * y1 - L2 * y1 - L3 * y2 - L1 * y3) / S / 2 | |
230 | - const y = (L3 * x2 + L2 * x1 + L1 * x3 - L1 * x2 - L2 * x3 - L3 * x1) / S / 2 | |
231 | - // 三点外接圆圆心坐标 | |
232 | - const center = new Vector3(x, y, 0) | |
233 | - return center | |
234 | -} | |
235 | - | |
236 | -export { arcXOY, flyArc } |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/Utils/common.ts
deleted
100644 → 0
1 | -import { | |
2 | - CatmullRomCurve3, | |
3 | - DoubleSide, | |
4 | - Group, | |
5 | - Mesh, | |
6 | - MeshBasicMaterial, | |
7 | - PlaneGeometry, | |
8 | - Texture, | |
9 | - TubeGeometry, | |
10 | - Vector3 | |
11 | -} from 'three' | |
12 | -import { punctuation } from '../world/Earth' | |
13 | - | |
14 | -/** | |
15 | - * 经纬度坐标转球面坐标 | |
16 | - * @param {地球半径} R | |
17 | - * @param {经度(角度值)} longitude | |
18 | - * @param {维度(角度值)} latitude | |
19 | - */ | |
20 | -export const lon2xyz = (R: number, longitude: number, latitude: number): Vector3 => { | |
21 | - let lon = (longitude * Math.PI) / 180 // 转弧度值 | |
22 | - const lat = (latitude * Math.PI) / 180 // 转弧度值 | |
23 | - lon = -lon // js坐标系z坐标轴对应经度-90度,而不是90度 | |
24 | - | |
25 | - // 经纬度坐标转球面坐标计算公式 | |
26 | - const x = R * Math.cos(lat) * Math.cos(lon) | |
27 | - const y = R * Math.sin(lat) | |
28 | - const z = R * Math.cos(lat) * Math.sin(lon) | |
29 | - // 返回球面坐标 | |
30 | - return new Vector3(x, y, z) | |
31 | -} | |
32 | - | |
33 | -// 创建波动光圈 | |
34 | -export const createWaveMesh = (options: { radius: number; lon: number; lat: number; textures: any }) => { | |
35 | - const geometry = new PlaneGeometry(1, 1) //默认在XOY平面上 | |
36 | - const texture = options.textures.aperture | |
37 | - | |
38 | - const material = new MeshBasicMaterial({ | |
39 | - color: 0xe99f68, | |
40 | - map: texture, | |
41 | - transparent: true, //使用背景透明的png贴图,注意开启透明计算 | |
42 | - opacity: 1.0, | |
43 | - depthWrite: false //禁止写入深度缓冲区数据 | |
44 | - }) | |
45 | - const mesh = new Mesh(geometry, material) | |
46 | - // 经纬度转球面坐标 | |
47 | - const coord = lon2xyz(options.radius * 1.001, options.lon, options.lat) | |
48 | - const size = options.radius * 0.12 //矩形平面Mesh的尺寸 | |
49 | - mesh.scale.set(size, size, size) //设置mesh大小 | |
50 | - mesh.userData['size'] = size //自顶一个属性,表示mesh静态大小 | |
51 | - mesh.userData['scale'] = Math.random() * 1.0 //自定义属性._s表示mesh在原始大小基础上放大倍数 光圈在原来mesh.size基础上1~2倍之间变化 | |
52 | - mesh.position.set(coord.x, coord.y, coord.z) | |
53 | - const coordVec3 = new Vector3(coord.x, coord.y, coord.z).normalize() | |
54 | - const meshNormal = new Vector3(0, 0, 1) | |
55 | - mesh.quaternion.setFromUnitVectors(meshNormal, coordVec3) | |
56 | - return mesh | |
57 | -} | |
58 | - | |
59 | -// 创建柱状 | |
60 | -export const createLightPillar = (options: { | |
61 | - radius: number | |
62 | - lon: number | |
63 | - lat: number | |
64 | - index: number | |
65 | - textures: Record<string, Texture> | |
66 | - punctuation: punctuation | |
67 | -}) => { | |
68 | - const height = options.radius * 0.3 | |
69 | - const geometry = new PlaneGeometry(options.radius * 0.05, height) | |
70 | - geometry.rotateX(Math.PI / 2) | |
71 | - geometry.translate(0, 0, height / 2) | |
72 | - const material = new MeshBasicMaterial({ | |
73 | - map: options.textures.light_column, | |
74 | - color: options.index == 0 ? options.punctuation.lightColumn.startColor : options.punctuation.lightColumn.endColor, | |
75 | - transparent: true, | |
76 | - side: DoubleSide, | |
77 | - depthWrite: false //是否对深度缓冲区有任何的影响 | |
78 | - }) | |
79 | - const mesh = new Mesh(geometry, material) | |
80 | - const group = new Group() | |
81 | - // 两个光柱交叉叠加 | |
82 | - group.add(mesh, mesh.clone().rotateZ(Math.PI / 2)) //几何体绕x轴旋转了,所以mesh旋转轴变为z | |
83 | - // 经纬度转球面坐标 | |
84 | - const SphereCoord = lon2xyz(options.radius, options.lon, options.lat) //SphereCoord球面坐标 | |
85 | - group.position.set(SphereCoord.x, SphereCoord.y, SphereCoord.z) //设置mesh位置 | |
86 | - const coordVec3 = new Vector3(SphereCoord.x, SphereCoord.y, SphereCoord.z).normalize() | |
87 | - const meshNormal = new Vector3(0, 0, 1) | |
88 | - group.quaternion.setFromUnitVectors(meshNormal, coordVec3) | |
89 | - return group | |
90 | -} | |
91 | - | |
92 | -// 光柱底座矩形平面 | |
93 | -export const createPointMesh = (options: { radius: number; lon: number; lat: number; material: MeshBasicMaterial }) => { | |
94 | - const geometry = new PlaneGeometry(1, 1) //默认在XOY平面上 | |
95 | - const mesh = new Mesh(geometry, options.material) | |
96 | - // 经纬度转球面坐标 | |
97 | - const coord = lon2xyz(options.radius * 1.001, options.lon, options.lat) | |
98 | - const size = options.radius * 0.05 // 矩形平面Mesh的尺寸 | |
99 | - mesh.scale.set(size, size, size) // 设置mesh大小 | |
100 | - | |
101 | - // 设置mesh位置 | |
102 | - mesh.position.set(coord.x, coord.y, coord.z) | |
103 | - const coordVec3 = new Vector3(coord.x, coord.y, coord.z).normalize() | |
104 | - const meshNormal = new Vector3(0, 0, 1) | |
105 | - mesh.quaternion.setFromUnitVectors(meshNormal, coordVec3) | |
106 | - return mesh | |
107 | -} | |
108 | - | |
109 | -// 获取点 | |
110 | -export const getCirclePoints = (option: any) => { | |
111 | - const list = [] | |
112 | - for (let j = 0; j < 2 * Math.PI - 0.1; j += (2 * Math.PI) / (option.number || 100)) { | |
113 | - list.push([ | |
114 | - parseFloat((Math.cos(j) * (option.radius || 10)).toFixed(2)), | |
115 | - 0, | |
116 | - parseFloat((Math.sin(j) * (option.radius || 10)).toFixed(2)) | |
117 | - ]) | |
118 | - } | |
119 | - if (option.closed) list.push(list[0]) | |
120 | - return list | |
121 | -} | |
122 | - | |
123 | -// 创建线 | |
124 | - | |
125 | -/** | |
126 | - * 创建动态的线 | |
127 | - */ | |
128 | -export const createAnimateLine = (option: any) => { | |
129 | - // 由多个点数组构成的曲线 通常用于道路 | |
130 | - const l: Array<any> = [] | |
131 | - option.pointList.forEach((e: Array<any>) => l.push(new Vector3(e[0], e[1], e[2]))) | |
132 | - const curve = new CatmullRomCurve3(l) // 曲线路径 | |
133 | - | |
134 | - // 管道体 | |
135 | - const tubeGeometry = new TubeGeometry(curve, option.number || 50, option.radius || 1, option.radialSegments) | |
136 | - return new Mesh(tubeGeometry, option.material) | |
137 | -} |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/shaders/earth/fragment.fs
deleted
100644 → 0
1 | -uniform vec3 glowColor; | |
2 | -uniform float bias; | |
3 | -uniform float power; | |
4 | -uniform float time; | |
5 | -varying vec3 vp; | |
6 | -varying vec3 vNormal; | |
7 | -varying vec3 vPositionNormal; | |
8 | -uniform float scale; | |
9 | -// 获取纹理 | |
10 | -uniform sampler2D map; | |
11 | -// 纹理坐标 | |
12 | -varying vec2 vUv; | |
13 | - | |
14 | -void main(void){ | |
15 | - float a = pow( bias + scale * abs(dot(vNormal, vPositionNormal)), power ); | |
16 | - if(vp.y > time && vp.y < time + 20.0) { | |
17 | - float t = smoothstep(0.0, 0.8, (1.0 - abs(0.5 - (vp.y - time) / 20.0)) / 3.0 ); | |
18 | - gl_FragColor = mix(gl_FragColor, vec4(glowColor, 1.0), t * t ); | |
19 | - } | |
20 | - gl_FragColor = mix(gl_FragColor, vec4( glowColor, 1.0 ), a); | |
21 | - float b = 0.8; | |
22 | - gl_FragColor = gl_FragColor + texture2D( map, vUv ); | |
23 | -} | |
\ No newline at end of file |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/shaders/earth/vertex.vs
deleted
100644 → 0
1 | - | |
2 | -varying vec2 vUv; | |
3 | -varying vec3 vNormal; | |
4 | -varying vec3 vp; | |
5 | -varying vec3 vPositionNormal; | |
6 | -void main(void){ | |
7 | - vUv = uv; | |
8 | - vNormal = normalize( normalMatrix * normal ); // 转换到视图空间 | |
9 | - vp = position; | |
10 | - vPositionNormal = normalize(( modelViewMatrix * vec4(position, 1.0) ).xyz); | |
11 | - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); | |
12 | -} | |
\ No newline at end of file |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/world/Assets.ts
deleted
100644 → 0
1 | -/** | |
2 | - * 资源文件 | |
3 | - * 把模型和图片分开进行加载 | |
4 | - */ | |
5 | - | |
6 | -interface ITextures { | |
7 | - name: string | |
8 | - url: string | |
9 | -} | |
10 | - | |
11 | -export interface IResources { | |
12 | - textures?: ITextures[] | |
13 | -} | |
14 | - | |
15 | -const fileSuffix = ['earth', 'gradient', 'redCircle', 'label', 'aperture', 'glow', 'light_column', 'aircraft'] | |
16 | -const textures: ITextures[] = [] | |
17 | - | |
18 | -const modules = import.meta.globEager("../../images/earth/*"); | |
19 | - | |
20 | -for(let item in modules) { | |
21 | - const n = item.split('/').pop() | |
22 | - if(n) { | |
23 | - textures.push({ | |
24 | - name: n.split('.')[0], | |
25 | - url: modules[item].default | |
26 | - }) | |
27 | - } | |
28 | -} | |
29 | - | |
30 | -const resources: IResources = { | |
31 | - textures | |
32 | -} | |
33 | - | |
34 | -export { resources } |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/world/Basic.ts
deleted
100644 → 0
1 | -/** | |
2 | - * 创建 threejs 四大天王 | |
3 | - * 场景、相机、渲染器、控制器 | |
4 | - */ | |
5 | - | |
6 | -import * as THREE from 'three' | |
7 | -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' | |
8 | - | |
9 | -export class Basic { | |
10 | - public scene!: THREE.Scene | |
11 | - public camera!: THREE.PerspectiveCamera | |
12 | - public renderer!: THREE.WebGLRenderer | |
13 | - public controls!: OrbitControls | |
14 | - public dom: HTMLElement | |
15 | - | |
16 | - constructor(dom: HTMLElement) { | |
17 | - this.dom = dom | |
18 | - this.initScenes() | |
19 | - this.setControls() | |
20 | - } | |
21 | - | |
22 | - /** | |
23 | - * 初始化场景 | |
24 | - */ | |
25 | - initScenes() { | |
26 | - this.scene = new THREE.Scene() | |
27 | - | |
28 | - this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100000) | |
29 | - this.camera.position.set(0, 30, -250) | |
30 | - | |
31 | - this.renderer = new THREE.WebGLRenderer({ | |
32 | - // canvas: this.dom, | |
33 | - alpha: true, // 透明 | |
34 | - antialias: true // 抗锯齿 | |
35 | - }) | |
36 | - this.renderer.setPixelRatio(window.devicePixelRatio) // 设置屏幕像素比 | |
37 | - this.renderer.setSize(window.innerWidth, window.innerHeight) // 设置渲染器宽高 | |
38 | - this.dom.appendChild(this.renderer.domElement) // 添加到dom中 | |
39 | - } | |
40 | - | |
41 | - /** | |
42 | - * 设置控制器 | |
43 | - */ | |
44 | - setControls() { | |
45 | - // 鼠标控制 相机,渲染dom | |
46 | - this.controls = new OrbitControls(this.camera, this.renderer.domElement) | |
47 | - | |
48 | - this.controls.autoRotateSpeed = 3 | |
49 | - // 使动画循环使用时阻尼或自转 意思是否有惯性 | |
50 | - this.controls.enableDamping = true | |
51 | - // 动态阻尼系数 就是鼠标拖拽旋转灵敏度 | |
52 | - this.controls.dampingFactor = 0.05 | |
53 | - // 是否可以缩放 | |
54 | - this.controls.enableZoom = true | |
55 | - // 设置相机距离原点的最远距离 | |
56 | - this.controls.minDistance = 100 | |
57 | - // 设置相机距离原点的最远距离 | |
58 | - this.controls.maxDistance = 300 | |
59 | - // 是否开启右键拖拽 | |
60 | - this.controls.enablePan = false | |
61 | - } | |
62 | -} |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/world/Earth.ts
deleted
100644 → 0
1 | -import { | |
2 | - BufferAttribute, | |
3 | - BufferGeometry, | |
4 | - Color, | |
5 | - DoubleSide, | |
6 | - Group, | |
7 | - Material, | |
8 | - Mesh, | |
9 | - MeshBasicMaterial, | |
10 | - NormalBlending, | |
11 | - Object3D, | |
12 | - Points, | |
13 | - PointsMaterial, | |
14 | - ShaderMaterial, | |
15 | - SphereGeometry, | |
16 | - Sprite, | |
17 | - SpriteMaterial, | |
18 | - Texture, | |
19 | - TextureLoader, | |
20 | - Vector3 | |
21 | -} from 'three' | |
22 | - | |
23 | -import { | |
24 | - createAnimateLine, | |
25 | - createLightPillar, | |
26 | - createPointMesh, | |
27 | - createWaveMesh, | |
28 | - getCirclePoints, | |
29 | - lon2xyz | |
30 | -} from '../Utils/common' | |
31 | -import gsap from 'gsap' | |
32 | -import { flyArc } from '../Utils/arc' | |
33 | -import earthVertex from '../shaders/earth/vertex.vs?raw' | |
34 | -import earthFragment from '../shaders/earth/fragment.fs?raw' | |
35 | - | |
36 | -export type punctuation = { | |
37 | - circleColor: number | |
38 | - lightColumn: { | |
39 | - startColor: number // 起点颜色 | |
40 | - endColor: number // 终点颜色 | |
41 | - } | |
42 | -} | |
43 | - | |
44 | -type options = { | |
45 | - data: { | |
46 | - startArray: { | |
47 | - name: string | |
48 | - E: number // 经度 | |
49 | - N: number // 维度 | |
50 | - } | |
51 | - endArray: { | |
52 | - name: string | |
53 | - E: number // 经度 | |
54 | - N: number // 维度 | |
55 | - }[] | |
56 | - }[] | |
57 | - dom: HTMLElement | |
58 | - textures: Record<string, Texture> // 贴图 | |
59 | - earth: { | |
60 | - radius: number // 地球半径 | |
61 | - rotateSpeed: number // 地球旋转速度 | |
62 | - isRotation: boolean // 地球组是否自转 | |
63 | - } | |
64 | - satellite: { | |
65 | - show: boolean // 是否显示卫星 | |
66 | - rotateSpeed: number // 旋转速度 | |
67 | - size: number // 卫星大小 | |
68 | - number: number // 一个圆环几个球 | |
69 | - } | |
70 | - punctuation: punctuation | |
71 | - flyLine: { | |
72 | - color: number // 飞线的颜色 | |
73 | - speed: number // 飞机拖尾线速度 | |
74 | - flyLineColor: number // 飞行线的颜色 | |
75 | - } | |
76 | -} | |
77 | -type uniforms = { | |
78 | - glowColor: { value: Color } | |
79 | - scale: { type: string; value: number } | |
80 | - bias: { type: string; value: number } | |
81 | - power: { type: string; value: number } | |
82 | - time: { type: string; value: any } | |
83 | - isHover: { value: boolean } | |
84 | - map: { value?: Texture } | |
85 | -} | |
86 | - | |
87 | -export default class earth { | |
88 | - public group: Group | |
89 | - public earthGroup: Group | |
90 | - | |
91 | - public around!: BufferGeometry | |
92 | - public aroundPoints!: Points<BufferGeometry, PointsMaterial> | |
93 | - | |
94 | - public options: options | |
95 | - public uniforms: uniforms | |
96 | - public timeValue: number | |
97 | - | |
98 | - public earth!: Mesh<SphereGeometry, ShaderMaterial> | |
99 | - public punctuationMaterial!: MeshBasicMaterial | |
100 | - public markupPoint: Group | |
101 | - public waveMeshArr: Object3D[] | |
102 | - | |
103 | - public circleLineList: any[] | |
104 | - public circleList: any[] | |
105 | - public x: number | |
106 | - public n: number | |
107 | - public isRotation: boolean | |
108 | - public flyLineArcGroup!: Group | |
109 | - | |
110 | - constructor(options: options) { | |
111 | - this.options = options | |
112 | - | |
113 | - this.group = new Group() | |
114 | - this.group.name = 'group' | |
115 | - this.group.scale.set(0, 0, 0) | |
116 | - this.earthGroup = new Group() | |
117 | - this.group.add(this.earthGroup) | |
118 | - this.earthGroup.name = 'EarthGroup' | |
119 | - | |
120 | - // 标注点效果 | |
121 | - this.markupPoint = new Group() | |
122 | - this.markupPoint.name = 'markupPoint' | |
123 | - this.waveMeshArr = [] | |
124 | - | |
125 | - // 卫星和标签 | |
126 | - this.circleLineList = [] | |
127 | - this.circleList = [] | |
128 | - this.x = 0 | |
129 | - this.n = 0 | |
130 | - | |
131 | - // 地球自转 | |
132 | - this.isRotation = this.options.earth.isRotation | |
133 | - | |
134 | - // 扫光动画 shader | |
135 | - this.timeValue = 200 | |
136 | - | |
137 | - this.uniforms = { | |
138 | - glowColor: { | |
139 | - value: new Color(0x0cd1eb) | |
140 | - }, | |
141 | - scale: { | |
142 | - type: 'f', | |
143 | - value: -1.0 | |
144 | - }, | |
145 | - bias: { | |
146 | - type: 'f', | |
147 | - value: 1.0 | |
148 | - }, | |
149 | - power: { | |
150 | - type: 'f', | |
151 | - value: 3.3 | |
152 | - }, | |
153 | - time: { | |
154 | - type: 'f', | |
155 | - value: this.timeValue | |
156 | - }, | |
157 | - isHover: { | |
158 | - value: false | |
159 | - }, | |
160 | - map: { | |
161 | - value: undefined | |
162 | - } | |
163 | - } | |
164 | - } | |
165 | - | |
166 | - async init(): Promise<void> { | |
167 | - return new Promise(resolve => { | |
168 | - const init = async () => { | |
169 | - this.createEarth() // 创建地球 | |
170 | - this.createEarthGlow() // 创建地球辉光 | |
171 | - this.createEarthAperture() // 创建地球的大气层 | |
172 | - await this.createMarkupPoint() // 创建柱状点位 | |
173 | - this.createAnimateCircle() // 创建环绕卫星 | |
174 | - this.createFlyLine() // 创建飞线 | |
175 | - this.show() | |
176 | - resolve() | |
177 | - } | |
178 | - init() | |
179 | - }) | |
180 | - } | |
181 | - | |
182 | - createEarth() { | |
183 | - const earth_geometry = new SphereGeometry(this.options.earth.radius, 50, 50) | |
184 | - const earth_border = new SphereGeometry(this.options.earth.radius + 10, 60, 60) | |
185 | - | |
186 | - const pointMaterial = new PointsMaterial({ | |
187 | - color: 0x81ffff, //设置颜色,默认 0xFFFFFF | |
188 | - transparent: true, | |
189 | - sizeAttenuation: true, | |
190 | - opacity: 0.1, | |
191 | - vertexColors: false, //定义材料是否使用顶点颜色,默认false ---如果该选项设置为true,则color属性失效 | |
192 | - size: 0.2 //定义粒子的大小。默认为1.0 | |
193 | - }) | |
194 | - const points = new Points(earth_border, pointMaterial) //将模型添加到场景 | |
195 | - | |
196 | - this.earthGroup.add(points) | |
197 | - | |
198 | - this.uniforms.map.value = this.options.textures.earth | |
199 | - | |
200 | - const earth_material = new ShaderMaterial({ | |
201 | - // wireframe:true, // 显示模型线条 | |
202 | - uniforms: this.uniforms as any, | |
203 | - vertexShader: earthVertex, | |
204 | - fragmentShader: earthFragment | |
205 | - }) | |
206 | - | |
207 | - earth_material.needsUpdate = true | |
208 | - this.earth = new Mesh(earth_geometry, earth_material) | |
209 | - this.earth.name = 'earth' | |
210 | - this.earthGroup.add(this.earth) | |
211 | - } | |
212 | - | |
213 | - createEarthGlow() { | |
214 | - const R = this.options.earth.radius //地球半径 | |
215 | - | |
216 | - // TextureLoader创建一个纹理加载器对象,可以加载图片作为纹理贴图 | |
217 | - const texture = this.options.textures.glow // 加载纹理贴图 | |
218 | - | |
219 | - // 创建精灵材质对象SpriteMaterial | |
220 | - const spriteMaterial = new SpriteMaterial({ | |
221 | - map: texture, // 设置精灵纹理贴图 | |
222 | - color: 0x4390d1, | |
223 | - transparent: true, //开启透明 | |
224 | - opacity: 0.7, // 可以通过透明度整体调节光圈 | |
225 | - depthWrite: false //禁止写入深度缓冲区数据 | |
226 | - }) | |
227 | - | |
228 | - // 创建表示地球光圈的精灵模型 | |
229 | - const sprite = new Sprite(spriteMaterial) | |
230 | - sprite.scale.set(R * 3.0, R * 3.0, 1) //适当缩放精灵 | |
231 | - this.earthGroup.add(sprite) | |
232 | - } | |
233 | - | |
234 | - createEarthAperture() { | |
235 | - const vertexShader = [ | |
236 | - 'varying vec3 vVertexWorldPosition;', | |
237 | - 'varying vec3 vVertexNormal;', | |
238 | - 'varying vec4 vFragColor;', | |
239 | - 'void main(){', | |
240 | - ' vVertexNormal = normalize(normalMatrix * normal);', //将法线转换到视图坐标系中 | |
241 | - ' vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;', //将顶点转换到世界坐标系中 | |
242 | - ' // set gl_Position', | |
243 | - ' gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);', | |
244 | - '}' | |
245 | - ].join('\n') | |
246 | - | |
247 | - //大气层效果 | |
248 | - const AeroSphere = { | |
249 | - uniforms: { | |
250 | - coeficient: { | |
251 | - type: 'f', | |
252 | - value: 1.0 | |
253 | - }, | |
254 | - power: { | |
255 | - type: 'f', | |
256 | - value: 3 | |
257 | - }, | |
258 | - glowColor: { | |
259 | - type: 'c', | |
260 | - value: new Color(0x4390d1) | |
261 | - } | |
262 | - }, | |
263 | - vertexShader: vertexShader, | |
264 | - fragmentShader: [ | |
265 | - 'uniform vec3 glowColor;', | |
266 | - 'uniform float coeficient;', | |
267 | - 'uniform float power;', | |
268 | - | |
269 | - 'varying vec3 vVertexNormal;', | |
270 | - 'varying vec3 vVertexWorldPosition;', | |
271 | - | |
272 | - 'varying vec4 vFragColor;', | |
273 | - | |
274 | - 'void main(){', | |
275 | - ' vec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition;', //世界坐标系中从相机位置到顶点位置的距离 | |
276 | - ' vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz;', //视图坐标系中从相机位置到顶点位置的距离 | |
277 | - ' viewCameraToVertex= normalize(viewCameraToVertex);', //规一化 | |
278 | - ' float intensity = pow(coeficient + dot(vVertexNormal, viewCameraToVertex), power);', | |
279 | - ' gl_FragColor = vec4(glowColor, intensity);', | |
280 | - '}' | |
281 | - ].join('\n') | |
282 | - } | |
283 | - //球体 辉光 大气层 | |
284 | - const material1 = new ShaderMaterial({ | |
285 | - uniforms: AeroSphere.uniforms, | |
286 | - vertexShader: AeroSphere.vertexShader, | |
287 | - fragmentShader: AeroSphere.fragmentShader, | |
288 | - blending: NormalBlending, | |
289 | - transparent: true, | |
290 | - depthWrite: false | |
291 | - }) | |
292 | - const sphere = new SphereGeometry(this.options.earth.radius + 0, 50, 50) | |
293 | - const mesh = new Mesh(sphere, material1) | |
294 | - this.earthGroup.add(mesh) | |
295 | - } | |
296 | - | |
297 | - async createMarkupPoint() { | |
298 | - await Promise.all( | |
299 | - this.options.data.map(async item => { | |
300 | - const radius = this.options.earth.radius | |
301 | - const lon = item.startArray.E //经度 | |
302 | - const lat = item.startArray.N //纬度 | |
303 | - | |
304 | - this.punctuationMaterial = new MeshBasicMaterial({ | |
305 | - color: this.options.punctuation.circleColor, | |
306 | - map: this.options.textures.label, | |
307 | - transparent: true, //使用背景透明的png贴图,注意开启透明计算 | |
308 | - depthWrite: false //禁止写入深度缓冲区数据 | |
309 | - }) | |
310 | - | |
311 | - const mesh = createPointMesh({ radius, lon, lat, material: this.punctuationMaterial }) //光柱底座矩形平面 | |
312 | - this.markupPoint.add(mesh) | |
313 | - const LightPillar = createLightPillar({ | |
314 | - radius: this.options.earth.radius, | |
315 | - lon, | |
316 | - lat, | |
317 | - index: 0, | |
318 | - textures: this.options.textures, | |
319 | - punctuation: this.options.punctuation | |
320 | - }) //光柱 | |
321 | - this.markupPoint.add(LightPillar) | |
322 | - const WaveMesh = createWaveMesh({ radius, lon, lat, textures: this.options.textures }) //波动光圈 | |
323 | - this.markupPoint.add(WaveMesh) | |
324 | - this.waveMeshArr.push(WaveMesh) | |
325 | - | |
326 | - await Promise.all( | |
327 | - item.endArray.map(obj => { | |
328 | - const lon = obj.E //经度 | |
329 | - const lat = obj.N //纬度 | |
330 | - const mesh = createPointMesh({ radius, lon, lat, material: this.punctuationMaterial }) //光柱底座矩形平面 | |
331 | - this.markupPoint.add(mesh) | |
332 | - const LightPillar = createLightPillar({ | |
333 | - radius: this.options.earth.radius, | |
334 | - lon, | |
335 | - lat, | |
336 | - index: 1, | |
337 | - textures: this.options.textures, | |
338 | - punctuation: this.options.punctuation | |
339 | - }) //光柱 | |
340 | - this.markupPoint.add(LightPillar) | |
341 | - const WaveMesh = createWaveMesh({ radius, lon, lat, textures: this.options.textures }) //波动光圈 | |
342 | - this.markupPoint.add(WaveMesh) | |
343 | - this.waveMeshArr.push(WaveMesh) | |
344 | - }) | |
345 | - ) | |
346 | - this.earthGroup.add(this.markupPoint) | |
347 | - }) | |
348 | - ) | |
349 | - } | |
350 | - | |
351 | - createAnimateCircle() { | |
352 | - // 创建 圆环 点 | |
353 | - const list = getCirclePoints({ | |
354 | - radius: this.options.earth.radius + 15, | |
355 | - number: 150, //切割数 | |
356 | - closed: true // 闭合 | |
357 | - }) | |
358 | - const mat = new MeshBasicMaterial({ | |
359 | - color: '#0c3172', | |
360 | - transparent: true, | |
361 | - opacity: 0.4, | |
362 | - side: DoubleSide | |
363 | - }) | |
364 | - const line = createAnimateLine({ | |
365 | - pointList: list, | |
366 | - material: mat, | |
367 | - number: 100, | |
368 | - radius: 0.1 | |
369 | - }) | |
370 | - this.earthGroup.add(line) | |
371 | - | |
372 | - // 在clone两条线出来 | |
373 | - const l2 = line.clone() | |
374 | - l2.scale.set(1.2, 1.2, 1.2) | |
375 | - l2.rotateZ(Math.PI / 6) | |
376 | - this.earthGroup.add(l2) | |
377 | - | |
378 | - const l3 = line.clone() | |
379 | - l3.scale.set(0.8, 0.8, 0.8) | |
380 | - l3.rotateZ(-Math.PI / 6) | |
381 | - this.earthGroup.add(l3) | |
382 | - | |
383 | - /** | |
384 | - * 旋转的球 | |
385 | - */ | |
386 | - const ball = new Mesh( | |
387 | - new SphereGeometry(this.options.satellite.size, 32, 32), | |
388 | - new MeshBasicMaterial({ | |
389 | - color: '#e0b187' // 745F4D | |
390 | - }) | |
391 | - ) | |
392 | - | |
393 | - const ball2 = new Mesh( | |
394 | - new SphereGeometry(this.options.satellite.size, 32, 32), | |
395 | - new MeshBasicMaterial({ | |
396 | - color: '#628fbb' // 324A62 | |
397 | - }) | |
398 | - ) | |
399 | - | |
400 | - const ball3 = new Mesh( | |
401 | - new SphereGeometry(this.options.satellite.size, 32, 32), | |
402 | - new MeshBasicMaterial({ | |
403 | - color: '#806bdf' //6D5AC4 | |
404 | - }) | |
405 | - ) | |
406 | - | |
407 | - this.circleLineList.push(line, l2, l3) | |
408 | - ball.name = ball2.name = ball3.name = '卫星' | |
409 | - | |
410 | - for (let i = 0; i < this.options.satellite.number; i++) { | |
411 | - const ball01 = ball.clone() | |
412 | - // 一根线上总共有几个球,根据数量平均分布一下 | |
413 | - const num = Math.floor(list.length / this.options.satellite.number) | |
414 | - ball01.position.set(list[num * (i + 1)][0] * 1, list[num * (i + 1)][1] * 1, list[num * (i + 1)][2] * 1) | |
415 | - line.add(ball01) | |
416 | - | |
417 | - const ball02 = ball2.clone() | |
418 | - const num02 = Math.floor(list.length / this.options.satellite.number) | |
419 | - ball02.position.set(list[num02 * (i + 1)][0] * 1, list[num02 * (i + 1)][1] * 1, list[num02 * (i + 1)][2] * 1) | |
420 | - l2.add(ball02) | |
421 | - | |
422 | - const ball03 = ball2.clone() | |
423 | - const num03 = Math.floor(list.length / this.options.satellite.number) | |
424 | - ball03.position.set(list[num03 * (i + 1)][0] * 1, list[num03 * (i + 1)][1] * 1, list[num03 * (i + 1)][2] * 1) | |
425 | - l3.add(ball03) | |
426 | - } | |
427 | - } | |
428 | - | |
429 | - createFlyLine() { | |
430 | - this.flyLineArcGroup = new Group() | |
431 | - this.flyLineArcGroup.userData['flyLineArray'] = [] | |
432 | - this.earthGroup.add(this.flyLineArcGroup) | |
433 | - this.options.data.forEach(cities => { | |
434 | - cities.endArray.forEach(item => { | |
435 | - // 调用函数flyArc绘制球面上任意两点之间飞线圆弧轨迹 | |
436 | - const arcline = flyArc( | |
437 | - this.options.earth.radius, | |
438 | - cities.startArray.E, | |
439 | - cities.startArray.N, | |
440 | - item.E, | |
441 | - item.N, | |
442 | - this.options.flyLine | |
443 | - ) | |
444 | - | |
445 | - this.flyLineArcGroup.add(arcline) // 飞线插入flyArcGroup中 | |
446 | - this.flyLineArcGroup.userData['flyLineArray'].push(arcline.userData['flyLine']) | |
447 | - }) | |
448 | - }) | |
449 | - } | |
450 | - | |
451 | - show() { | |
452 | - gsap.to(this.group.scale, { | |
453 | - x: 1, | |
454 | - y: 1, | |
455 | - z: 1, | |
456 | - duration: 2, | |
457 | - ease: 'Quadratic' | |
458 | - }) | |
459 | - } | |
460 | - | |
461 | - render() { | |
462 | - this.flyLineArcGroup?.userData['flyLineArray']?.forEach((fly: any) => { | |
463 | - fly.rotation.z += this.options.flyLine.speed // 调节飞线速度 | |
464 | - if (fly.rotation.z >= fly.flyEndAngle) fly.rotation.z = 0 | |
465 | - }) | |
466 | - | |
467 | - if (this.isRotation) { | |
468 | - this.earthGroup.rotation.y += this.options.earth.rotateSpeed | |
469 | - } | |
470 | - | |
471 | - this.circleLineList.forEach(e => { | |
472 | - e.rotateY(this.options.satellite.rotateSpeed) | |
473 | - }) | |
474 | - | |
475 | - this.uniforms.time.value = | |
476 | - this.uniforms.time.value < -this.timeValue ? this.timeValue : this.uniforms.time.value - 1 | |
477 | - | |
478 | - if (this.waveMeshArr.length) { | |
479 | - this.waveMeshArr.forEach((mesh: any) => { | |
480 | - mesh.userData['scale'] += 0.007 | |
481 | - mesh.scale.set( | |
482 | - mesh.userData['size'] * mesh.userData['scale'], | |
483 | - mesh.userData['size'] * mesh.userData['scale'], | |
484 | - mesh.userData['size'] * mesh.userData['scale'] | |
485 | - ) | |
486 | - if (mesh.userData['scale'] <= 1.5) { | |
487 | - (mesh.material as Material).opacity = (mesh.userData['scale'] - 1) * 2 //2等于1/(1.5-1.0),保证透明度在0~1之间变化 | |
488 | - } else if (mesh.userData['scale'] > 1.5 && mesh.userData['scale'] <= 2) { | |
489 | - (mesh.material as Material).opacity = 1 - (mesh.userData['scale'] - 1.5) * 2 //2等于1/(2.0-1.5) mesh缩放2倍对应0 缩放1.5被对应1 | |
490 | - } else { | |
491 | - mesh.userData['scale'] = 1 | |
492 | - } | |
493 | - }) | |
494 | - } | |
495 | - } | |
496 | -} |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/code/world/Resources.ts
deleted
100644 → 0
1 | -/** | |
2 | - * 资源管理和加载 | |
3 | - */ | |
4 | -import { LoadingManager, Texture, TextureLoader } from 'three' | |
5 | -import { loadingStart, loadingFinish, loadingError } from '@/utils' | |
6 | -import { resources } from './Assets' | |
7 | -export class Resources { | |
8 | - private manager!: LoadingManager | |
9 | - private callback: () => void | |
10 | - private textureLoader!: InstanceType<typeof TextureLoader> | |
11 | - public textures: Record<string, Texture> | |
12 | - constructor(callback: () => void) { | |
13 | - this.callback = callback // 资源加载完成的回调 | |
14 | - this.textures = {} // 贴图对象 | |
15 | - this.setLoadingManager() | |
16 | - this.loadResources() | |
17 | - } | |
18 | - | |
19 | - /** | |
20 | - * 管理加载状态 | |
21 | - */ | |
22 | - private setLoadingManager() { | |
23 | - this.manager = new LoadingManager() | |
24 | - // 开始加载 | |
25 | - this.manager.onStart = () => { | |
26 | - loadingStart() | |
27 | - } | |
28 | - // 加载完成 | |
29 | - this.manager.onLoad = () => { | |
30 | - this.callback() | |
31 | - } | |
32 | - // 正在进行中 | |
33 | - this.manager.onProgress = url => { | |
34 | - loadingFinish() | |
35 | - } | |
36 | - | |
37 | - this.manager.onError = url => { | |
38 | - loadingError() | |
39 | - window['$message'].error('数据加载失败,请刷新重试!') | |
40 | - } | |
41 | - } | |
42 | - | |
43 | - /** | |
44 | - * 加载资源 | |
45 | - */ | |
46 | - private loadResources(): void { | |
47 | - this.textureLoader = new TextureLoader(this.manager) | |
48 | - resources.textures?.forEach(item => { | |
49 | - this.textureLoader.load(item.url, t => { | |
50 | - this.textures[item.name] = t | |
51 | - }) | |
52 | - }) | |
53 | - } | |
54 | -} |
1 | -import { MeshBasicMaterial, PerspectiveCamera, Scene, ShaderMaterial, WebGLRenderer } from 'three' | |
2 | -import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' | |
3 | -// interfaces | |
4 | -import { IWord } from '../interfaces/IWord' | |
5 | -import { Basic } from './Basic' | |
6 | -import { Resources } from './Resources' | |
7 | -// earth | |
8 | -import Earth from './Earth' | |
9 | - | |
10 | -export default class World { | |
11 | - public basic: Basic | |
12 | - public scene: Scene | |
13 | - public camera: PerspectiveCamera | |
14 | - public renderer: WebGLRenderer | |
15 | - public controls: OrbitControls | |
16 | - public material!: ShaderMaterial | MeshBasicMaterial | |
17 | - public resources: Resources | |
18 | - public option: IWord | |
19 | - public earth!: Earth | |
20 | - | |
21 | - constructor(option: IWord) { | |
22 | - /** | |
23 | - * 加载资源 | |
24 | - */ | |
25 | - this.option = option | |
26 | - this.basic = new Basic(option.dom) | |
27 | - this.scene = this.basic.scene | |
28 | - this.renderer = this.basic.renderer | |
29 | - this.controls = this.basic.controls | |
30 | - this.camera = this.basic.camera | |
31 | - this.updateSize() | |
32 | - this.resources = new Resources(async () => { | |
33 | - await this.createEarth() | |
34 | - // 开始渲染 | |
35 | - this.render() | |
36 | - }) | |
37 | - } | |
38 | - | |
39 | - async createEarth(data?: any) { | |
40 | - // 资源加载完成,开始制作地球,注释在new Earth()类型里面 | |
41 | - this.earth = new Earth({ | |
42 | - data: data || this.option.data, | |
43 | - dom: this.option.dom, | |
44 | - textures: this.resources.textures, | |
45 | - earth: { | |
46 | - radius: 50, | |
47 | - rotateSpeed: 0.002, | |
48 | - isRotation: true | |
49 | - }, | |
50 | - satellite: { | |
51 | - show: true, | |
52 | - rotateSpeed: -0.01, | |
53 | - size: 1, | |
54 | - number: 2 | |
55 | - }, | |
56 | - punctuation: { | |
57 | - circleColor: 0x3892ff, | |
58 | - lightColumn: { | |
59 | - startColor: 0xe4007f, // 起点颜色 | |
60 | - endColor: 0xffffff // 终点颜色 | |
61 | - } | |
62 | - }, | |
63 | - flyLine: { | |
64 | - color: 0xf3ae76, // 飞线的颜色 | |
65 | - flyLineColor: 0xff7714, // 飞行线的颜色 | |
66 | - speed: 0.004 // 拖尾飞线的速度 | |
67 | - } | |
68 | - }) | |
69 | - | |
70 | - this.scene.add(this.earth.group) | |
71 | - await this.earth.init() | |
72 | - } | |
73 | - | |
74 | - /** | |
75 | - * 渲染函数 | |
76 | - */ | |
77 | - public render() { | |
78 | - requestAnimationFrame(this.render.bind(this)) | |
79 | - this.renderer.render(this.scene, this.camera) | |
80 | - this.controls && this.controls.update() | |
81 | - this.earth && this.earth.render() | |
82 | - } | |
83 | - | |
84 | - // 更新 | |
85 | - public updateSize(width?: number, height?: number) { | |
86 | - let w = width || this.option.width | |
87 | - let h = height || this.option.height | |
88 | - // 取小值 | |
89 | - if (w < h) h = w | |
90 | - else w = h | |
91 | - | |
92 | - this.renderer.setSize(w, h) | |
93 | - this.camera.aspect = w / h | |
94 | - this.camera.updateProjectionMatrix() | |
95 | - } | |
96 | - | |
97 | - // 数据更新重新渲染 | |
98 | - public updateData(data?: any) { | |
99 | - if (!this.earth.group) return | |
100 | - // 先删除旧的 | |
101 | - this.scene.remove(this.earth.group) | |
102 | - // 递归遍历组对象group释放所有后代网格模型绑定几何体占用内存 | |
103 | - this.earth.group.traverse((obj: any) => { | |
104 | - if (obj.type === 'Mesh') { | |
105 | - obj.geometry.dispose() | |
106 | - obj.material.dispose() | |
107 | - } | |
108 | - }) | |
109 | - // 重新创建 | |
110 | - this.createEarth(data) | |
111 | - } | |
112 | -} |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/config.ts
deleted
100644 → 0
1 | -import { PublicConfigClass } from '@/packages/public' | |
2 | -import { CreateComponentType } from '@/packages/index.d' | |
3 | -import { chartInitConfig } from '@/settings/designSetting' | |
4 | -import { ThreeEarth01Config } from './index' | |
5 | -import dataJson from './data.json' | |
6 | -import cloneDeep from 'lodash/cloneDeep' | |
7 | - | |
8 | -export const option = { | |
9 | - dataset: dataJson | |
10 | -} | |
11 | - | |
12 | -export default class Config extends PublicConfigClass implements CreateComponentType { | |
13 | - public key = ThreeEarth01Config.key | |
14 | - public attr = { ...chartInitConfig, w: 800, h: 800, zIndex: -1 } | |
15 | - public chartConfig = cloneDeep(ThreeEarth01Config) | |
16 | - public option = cloneDeep(option) | |
17 | -} |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/config.vue
deleted
100644 → 0
1 | -<template></template> | |
2 | - | |
3 | -<script setup lang="ts"> | |
4 | -import { PropType } from 'vue' | |
5 | -import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' | |
6 | -import { option } from './config.vue' | |
7 | - | |
8 | -const props = defineProps({ | |
9 | - optionData: { | |
10 | - type: Object as PropType<typeof option>, | |
11 | - required: true | |
12 | - } | |
13 | -}) | |
14 | -</script> |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/data.json
deleted
100644 → 0
1 | -[ | |
2 | - { | |
3 | - "startArray": { | |
4 | - "name": "杭州", | |
5 | - "N": 30.246026, | |
6 | - "E": 120.210792 | |
7 | - }, | |
8 | - "endArray": [ | |
9 | - { | |
10 | - "name": "曼谷", | |
11 | - "N": 22, | |
12 | - "E": 100.49074172973633 | |
13 | - }, | |
14 | - { | |
15 | - "name": "澳大利亚", | |
16 | - "N": -23.68477416688374, | |
17 | - "E": 133.857421875 | |
18 | - }, | |
19 | - | |
20 | - { | |
21 | - "name": "新疆维吾尔自治区", | |
22 | - "N": 41.748, | |
23 | - "E": 84.9023 | |
24 | - }, | |
25 | - | |
26 | - { | |
27 | - "name": "德黑兰", | |
28 | - "N": 35, | |
29 | - "E": 51 | |
30 | - }, | |
31 | - { | |
32 | - "name": "德黑兰", | |
33 | - "N": 35, | |
34 | - "E": 51 | |
35 | - }, | |
36 | - { | |
37 | - "name": "美国", | |
38 | - "N": 34.125447565116126, | |
39 | - "E": 241.7431640625 | |
40 | - }, | |
41 | - { | |
42 | - "name": "英国", | |
43 | - "N": 51.508742458803326, | |
44 | - "E": 359.82421875 | |
45 | - }, | |
46 | - { | |
47 | - "name": "巴西", | |
48 | - "N": -9.96885060854611, | |
49 | - "E": 668.1445312499999 | |
50 | - } | |
51 | - ] | |
52 | - }, | |
53 | - { | |
54 | - "startArray": { | |
55 | - "name": "北京", | |
56 | - "N": 39.89491, | |
57 | - "E": 116.322056 | |
58 | - }, | |
59 | - "endArray": [ | |
60 | - { | |
61 | - "name": "西藏", | |
62 | - "N": 29.660361, | |
63 | - "E": 91.132212 | |
64 | - }, | |
65 | - { | |
66 | - "name": "广西", | |
67 | - "N": 22.830824, | |
68 | - "E": 108.30616 | |
69 | - }, | |
70 | - | |
71 | - { | |
72 | - "name": "江西", | |
73 | - "N": 28.676493, | |
74 | - "E": 115.892151 | |
75 | - }, | |
76 | - | |
77 | - { | |
78 | - "name": "贵阳", | |
79 | - "N": 26.647661, | |
80 | - "E": 106.630153 | |
81 | - } | |
82 | - ] | |
83 | - } | |
84 | -] |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/aircraft.png
deleted
100644 → 0
3.58 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/aperture.png
deleted
100644 → 0
12.7 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/earth.png
deleted
100644 → 0
566 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/glow.png
deleted
100644 → 0
29.3 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/gradient.png
deleted
100644 → 0
5.46 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/label-old.png
deleted
100644 → 0
504 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/label.png
deleted
100644 → 0
12.7 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/light_column.png
deleted
100644 → 0
4.56 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/images/earth/redCircle.png
deleted
100644 → 0
42.1 KB
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/index.ts
deleted
100644 → 0
1 | -import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d' | |
2 | -import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d' | |
3 | - | |
4 | -export const ThreeEarth01Config: ConfigType = { | |
5 | - key: 'ThreeEarth01', | |
6 | - chartKey: 'VThreeEarth01', | |
7 | - conKey: 'VCThreeEarth01', | |
8 | - title: '三维地球', | |
9 | - category: ChatCategoryEnum.THREEDANIMATION, | |
10 | - categoryName: ChatCategoryEnumName.THREEDANIMATION, | |
11 | - package: PackagesCategoryEnum.ARTOONS, | |
12 | - chartFrame: ChartFrameEnum.STATIC, | |
13 | - image: 'threeEarth01.png' | |
14 | -} |
src/packages/components/Artoons/ThreeDAnimations/ThreeEarth01/index.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <div ref="chartRef"></div> | |
3 | -</template> | |
4 | - | |
5 | -<script setup lang="ts"> | |
6 | -import { onMounted, PropType, ref, toRefs, watch } from 'vue' | |
7 | -import { CreateComponentType } from '@/packages' | |
8 | -import { useChartDataFetch } from '@/hooks' | |
9 | -import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
10 | -import { option } from './config.vue' | |
11 | -import World from './code/world/Word' | |
12 | -import throttle from 'lodash/throttle' | |
13 | - | |
14 | -const props = defineProps({ | |
15 | - chartConfig: { | |
16 | - type: Object as PropType<CreateComponentType & typeof option>, | |
17 | - required: true | |
18 | - } | |
19 | -}) | |
20 | - | |
21 | -const chartEditStore = useChartEditStore() | |
22 | - | |
23 | -const chartRef = ref<HTMLElement>() | |
24 | -const { w, h } = toRefs(props.chartConfig.attr) | |
25 | -let threeClassInstance: World | |
26 | - | |
27 | -// 初始化 | |
28 | -const init = () => { | |
29 | - const dom: HTMLElement | undefined = chartRef.value | |
30 | - if (dom) { | |
31 | - threeClassInstance = new World({ | |
32 | - dom: dom, | |
33 | - data: props.chartConfig.option.dataset, | |
34 | - width: w.value, | |
35 | - height: h.value | |
36 | - }) | |
37 | - } | |
38 | -} | |
39 | - | |
40 | -const updateData = (data: any) => { | |
41 | - try { | |
42 | - threeClassInstance.updateData(data) | |
43 | - } catch (error) { | |
44 | - console.log(error) | |
45 | - } | |
46 | -} | |
47 | - | |
48 | -// 改变大小 | |
49 | -watch( | |
50 | - () => [w.value, h.value], | |
51 | - throttle(([newWidth], [newHeight]) => { | |
52 | - threeClassInstance.updateSize(newWidth, newHeight) | |
53 | - }, 100) | |
54 | -) | |
55 | - | |
56 | -watch( | |
57 | - () => props.chartConfig.option.dataset, | |
58 | - (newData: any) => { | |
59 | - updateData(newData) | |
60 | - }, | |
61 | - { | |
62 | - deep: false | |
63 | - } | |
64 | -) | |
65 | - | |
66 | -// DOM 渲染之后进行初始化 | |
67 | -onMounted(() => { | |
68 | - try { | |
69 | - if (navigator.userAgent.indexOf('Chrome') < -1 || navigator.userAgent.indexOf('Edg') < -1) { | |
70 | - window['$message'].error('三维地图组件仅在【谷歌】浏览器上能正常展示!') | |
71 | - chartEditStore.removeComponentList(undefined, false) | |
72 | - return | |
73 | - } | |
74 | - init() | |
75 | - } catch (error) { | |
76 | - console.log(error) | |
77 | - } | |
78 | -}) | |
79 | - | |
80 | -useChartDataFetch(props.chartConfig, useChartEditStore, updateData) | |
81 | -</script> |
src/packages/components/Artoons/ThreeDAnimations/index.ts
deleted
100644 → 0
src/packages/components/Artoons/TwoDAnimations/WaterPolo/config.ts
deleted
100644 → 0
1 | -import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public' | |
2 | -import { CreateComponentType } from '@/packages/index.d' | |
3 | -import { WaterPoloConfig } from './index' | |
4 | -import cloneDeep from 'lodash/cloneDeep' | |
5 | - | |
6 | -export const shapes = [ | |
7 | - { | |
8 | - label: '圆形', | |
9 | - value: 'circle' | |
10 | - }, | |
11 | - { | |
12 | - label: '正方形', | |
13 | - value: 'rect' | |
14 | - }, | |
15 | - { | |
16 | - label: '带圆角的正方形', | |
17 | - value: 'roundRect' | |
18 | - }, | |
19 | - { | |
20 | - label: '正三角形', | |
21 | - value: 'triangle' | |
22 | - }, | |
23 | - { | |
24 | - label: '菱形', | |
25 | - value: 'diamond' | |
26 | - }, | |
27 | - { | |
28 | - label: '水滴', | |
29 | - value: 'pin' | |
30 | - }, | |
31 | - { | |
32 | - label: '箭头', | |
33 | - value: 'arrow' | |
34 | - }, | |
35 | -] | |
36 | - | |
37 | -export const includes = [] | |
38 | - | |
39 | -export const option = { | |
40 | - dataset: 0.5, | |
41 | - series: [ | |
42 | - { | |
43 | - type: 'liquidFill', | |
44 | - shape: shapes[0].value, | |
45 | - radius: '90%', | |
46 | - data: [0], | |
47 | - center: ['50%', '50%'], | |
48 | - color: [ | |
49 | - { | |
50 | - type: 'linear', | |
51 | - x: 0, | |
52 | - y: 0, | |
53 | - x2: 0, | |
54 | - y2: 1, | |
55 | - colorStops: [ | |
56 | - { | |
57 | - offset: 0, | |
58 | - color: '#446bf5', | |
59 | - }, | |
60 | - { | |
61 | - offset: 1, | |
62 | - color: '#2ca3e2', | |
63 | - }, | |
64 | - ], | |
65 | - globalCoord: false, | |
66 | - }, | |
67 | - ], | |
68 | - backgroundStyle: { | |
69 | - borderWidth: 1, | |
70 | - color: 'rgba(51, 66, 127, 0.7)', | |
71 | - }, | |
72 | - label: { | |
73 | - normal: { | |
74 | - textStyle: { | |
75 | - fontSize: 50, | |
76 | - color: '#fff', | |
77 | - }, | |
78 | - }, | |
79 | - }, | |
80 | - outline: { | |
81 | - show: false, | |
82 | - borderDistance: 10, | |
83 | - itemStyle: { | |
84 | - borderWidth: 2, | |
85 | - borderColor: '#112165' | |
86 | - } | |
87 | - } | |
88 | - } | |
89 | - ] | |
90 | -} | |
91 | - | |
92 | -export default class Config extends PublicConfigClass implements CreateComponentType | |
93 | -{ | |
94 | - public key = WaterPoloConfig.key | |
95 | - public chartConfig = cloneDeep(WaterPoloConfig) | |
96 | - public option = echartOptionProfixHandle(option, includes) | |
97 | -} |
src/packages/components/Artoons/TwoDAnimations/WaterPolo/config.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <CollapseItem | |
3 | - v-for="(item, index) in seriesList" | |
4 | - :key="index" | |
5 | - name="水球" | |
6 | - :expanded="true" | |
7 | - > | |
8 | - <SettingItemBox name="内容"> | |
9 | - <SettingItem name="数值"> | |
10 | - <n-input-number | |
11 | - v-model:value="item.data[0]" | |
12 | - :min="0" | |
13 | - :step="0.01" | |
14 | - size="small" | |
15 | - placeholder="水球数值" | |
16 | - ></n-input-number> | |
17 | - </SettingItem> | |
18 | - <SettingItem name="形状"> | |
19 | - <n-select v-model:value="item.shape" :options="shapes" placeholder="选择形状" /> | |
20 | - </SettingItem> | |
21 | - <SettingItem name="文本"> | |
22 | - <n-input-number v-model:value="item.label.normal.textStyle.fontSize" :min="0" :step="1" size="small" placeholder="文字大小"> | |
23 | - </n-input-number> | |
24 | - </SettingItem> | |
25 | - <SettingItem name="颜色1"> | |
26 | - <n-color-picker | |
27 | - size="small" | |
28 | - :modes="['hex']" | |
29 | - v-model:value="item.color[0].colorStops[0].color" | |
30 | - ></n-color-picker> | |
31 | - </SettingItem> | |
32 | - <SettingItem name="颜色2"> | |
33 | - <n-color-picker | |
34 | - size="small" | |
35 | - :modes="['hex']" | |
36 | - v-model:value="item.color[0].colorStops[1].color" | |
37 | - ></n-color-picker> | |
38 | - </SettingItem> | |
39 | - </SettingItemBox> | |
40 | - <SettingItemBox name="背景" :alone="true"> | |
41 | - <SettingItem> | |
42 | - <n-color-picker | |
43 | - size="small" | |
44 | - :modes="['hex']" | |
45 | - v-model:value="item.backgroundStyle.color" | |
46 | - ></n-color-picker> | |
47 | - </SettingItem> | |
48 | - </SettingItemBox> | |
49 | - </CollapseItem> | |
50 | -</template> | |
51 | - | |
52 | -<script setup lang="ts"> | |
53 | -import { PropType, computed } from 'vue' | |
54 | -import { option, shapes } from './config' | |
55 | -import { | |
56 | - CollapseItem, | |
57 | - SettingItemBox, | |
58 | - SettingItem, | |
59 | -} from '@/components/Pages/ChartItemSetting' | |
60 | - | |
61 | -const props = defineProps({ | |
62 | - optionData: { | |
63 | - type: Object as PropType<typeof option>, | |
64 | - required: true, | |
65 | - }, | |
66 | -}) | |
67 | - | |
68 | -const seriesList = computed(() => { | |
69 | - return props.optionData.series | |
70 | -}) | |
71 | -</script> |
src/packages/components/Artoons/TwoDAnimations/WaterPolo/index.ts
deleted
100644 → 0
1 | -import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d' | |
2 | -import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d' | |
3 | - | |
4 | -export const WaterPoloConfig: ConfigType = { | |
5 | - key: 'WaterPolo', | |
6 | - chartKey: 'VWaterPolo', | |
7 | - conKey: 'VCWaterPolo', | |
8 | - title: '水球图', | |
9 | - category: ChatCategoryEnum.TWODANIMATION, | |
10 | - categoryName: ChatCategoryEnumName.TWODANIMATION, | |
11 | - package: PackagesCategoryEnum.ARTOONS, | |
12 | - chartFrame: ChartFrameEnum.COMMON, | |
13 | - image: 'water_WaterPolo.png' | |
14 | -} |
src/packages/components/Artoons/TwoDAnimations/WaterPolo/index.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <v-chart :theme="themeColor" :option="option.value" autoresize></v-chart> | |
3 | -</template> | |
4 | - | |
5 | -<script setup lang="ts"> | |
6 | -import { PropType, watch, reactive } from 'vue' | |
7 | -import VChart from 'vue-echarts' | |
8 | -import { use } from 'echarts/core' | |
9 | -import 'echarts-liquidfill/src/liquidFill.js' | |
10 | -import { CanvasRenderer } from 'echarts/renderers' | |
11 | -import { GridComponent } from 'echarts/components' | |
12 | -import config from './config' | |
13 | -import { isPreview, isString, isNumber } from '@/utils' | |
14 | -import { chartColorsSearch, defaultTheme } from '@/settings/chartThemes/index' | |
15 | -import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' | |
16 | -import { useChartDataFetch } from '@/hooks' | |
17 | - | |
18 | -const props = defineProps({ | |
19 | - themeSetting: { | |
20 | - type: Object, | |
21 | - required: true | |
22 | - }, | |
23 | - themeColor: { | |
24 | - type: Object, | |
25 | - required: true | |
26 | - }, | |
27 | - chartConfig: { | |
28 | - type: Object as PropType<config>, | |
29 | - required: true | |
30 | - } | |
31 | -}) | |
32 | - | |
33 | -use([CanvasRenderer, GridComponent]) | |
34 | - | |
35 | -const chartEditStore = useChartEditStore() | |
36 | - | |
37 | -const option = reactive({ | |
38 | - value: {} | |
39 | -}) | |
40 | - | |
41 | -// 渐变色处理 | |
42 | -watch( | |
43 | - () => chartEditStore.getEditCanvasConfig.chartThemeColor, | |
44 | - (newColor: keyof typeof chartColorsSearch) => { | |
45 | - try { | |
46 | - if (!isPreview()) { | |
47 | - const themeColor = chartColorsSearch[newColor] || chartColorsSearch[defaultTheme] | |
48 | - // 背景颜色 | |
49 | - props.chartConfig.option.series[0].backgroundStyle.color = themeColor[2] | |
50 | - // 水球颜色 | |
51 | - props.chartConfig.option.series[0].color[0].colorStops = [ | |
52 | - { | |
53 | - offset: 0, | |
54 | - color: themeColor[0] | |
55 | - }, | |
56 | - { | |
57 | - offset: 1, | |
58 | - color: themeColor[1] | |
59 | - } | |
60 | - ] | |
61 | - } | |
62 | - option.value = props.chartConfig.option | |
63 | - } catch (error) { | |
64 | - console.log(error) | |
65 | - } | |
66 | - }, | |
67 | - { | |
68 | - immediate: true | |
69 | - } | |
70 | -) | |
71 | - | |
72 | -// 数据处理 | |
73 | -const dataHandle = (newData: number | string) => { | |
74 | - newData = isString(newData) ? parseFloat(newData) : newData | |
75 | - return parseFloat(newData.toFixed(2)) | |
76 | -} | |
77 | - | |
78 | -// 编辑 | |
79 | -watch( | |
80 | - () => props.chartConfig.option.dataset, | |
81 | - newData => { | |
82 | - if (!isString(newData) && !isNumber(newData)) return | |
83 | - props.chartConfig.option.series[0].data = [dataHandle(newData)] | |
84 | - option.value = props.chartConfig.option | |
85 | - }, | |
86 | - { | |
87 | - immediate: true, | |
88 | - deep: false | |
89 | - } | |
90 | -) | |
91 | - | |
92 | -// 预览 | |
93 | -useChartDataFetch(props.chartConfig, useChartEditStore, (newData: number) => { | |
94 | - // @ts-ignore | |
95 | - option.value.series[0].data = [dataHandle(newData)] | |
96 | -}) | |
97 | -</script> |
src/packages/components/Artoons/TwoDAnimations/index.ts
deleted
100644 → 0
src/packages/components/Artoons/index.d.ts
deleted
100644 → 0
1 | -export enum ChatCategoryEnum { | |
2 | - TWODANIMATION = 'TwoDAnimations', | |
3 | - | |
4 | - THREEDANIMATION = 'ThreeDAnimations', | |
5 | - TITLE = 'Titles', | |
6 | - MORE = 'Mores', | |
7 | - | |
8 | -} | |
9 | - | |
10 | -export enum ChatCategoryEnumName { | |
11 | - TITLE = '标题', | |
12 | - TWODANIMATION = '2D动画', | |
13 | - THREEDANIMATION = '3D动画', | |
14 | - | |
15 | - MORE = '更多', | |
16 | -} |
src/packages/components/Artoons/index.ts
deleted
100644 → 0
1 | +import { PublicConfigClass } from '@/packages/public' | |
2 | +import { CreateComponentType } from '@/packages/index.d' | |
3 | +import { LeftCenterRightHeadConfig } from './index' | |
4 | +import cloneDeep from 'lodash/cloneDeep' | |
5 | + | |
6 | +export const option = { | |
7 | + dataset: '物联网平台数据统计', | |
8 | + bgSrc: 'src/assets/images/chart/headbackground/bg_top.png', | |
9 | + fontSize: 36, | |
10 | + showRight:true, | |
11 | + textColor:'#00f6ff', | |
12 | + textRightSizeColor:'#ffffff', | |
13 | + textRightFontSize:14, | |
14 | + x:0, | |
15 | + y:0, | |
16 | + xT:0, | |
17 | + yT:0, | |
18 | +} | |
19 | + | |
20 | +export default class Config extends PublicConfigClass implements CreateComponentType { | |
21 | + public key = LeftCenterRightHeadConfig.key | |
22 | + public chartConfig = cloneDeep(LeftCenterRightHeadConfig) | |
23 | + public option = cloneDeep(option) | |
24 | +} | ... | ... |
1 | +<template> | |
2 | + <collapse-item name="信息" :expanded="true"> | |
3 | + <setting-item-box name="背景选择" :alone="true"> | |
4 | + <setting-item> | |
5 | + <n-select | |
6 | + size="small" | |
7 | + placeholder="请选择您要使用的背景" | |
8 | + style="width: 250px" | |
9 | + v-model:value="selectValue" | |
10 | + :options="selectBgOptions" | |
11 | + @update:value="selectBgValueHandle" | |
12 | + /> | |
13 | + </setting-item> | |
14 | + </setting-item-box> | |
15 | + <setting-item-box name="文字" :alone="true"> | |
16 | + <setting-item> | |
17 | + <n-input v-model:value="optionData.dataset" size="small"></n-input> | |
18 | + </setting-item> | |
19 | + </setting-item-box> | |
20 | + </collapse-item> | |
21 | + <collapse-item name="样式" :expanded="true"> | |
22 | + <setting-item-box name="文字"> | |
23 | + <setting-item name="字体大小"> | |
24 | + <n-input-number v-model:value="optionData.fontSize" size="small" placeholder="字体大小"></n-input-number> | |
25 | + </setting-item> | |
26 | + </setting-item-box> | |
27 | + <setting-item-box name="文字颜色"> | |
28 | + <setting-item name="颜色"> | |
29 | + <n-color-picker size="small" :modes="['hex']" v-model:value="optionData.textColor"></n-color-picker> | |
30 | + </setting-item> | |
31 | + </setting-item-box> | |
32 | + <setting-item-box name="位置x轴"> | |
33 | + <setting-item name="字体位置x轴"> | |
34 | + <n-input-number v-model:value="optionData.x" size="small" placeholder="字体位置"></n-input-number> | |
35 | + </setting-item> | |
36 | + </setting-item-box> | |
37 | + <setting-item-box name="位置y轴"> | |
38 | + <setting-item name="字体位置y轴"> | |
39 | + <n-input-number v-model:value="optionData.y" size="small" placeholder="字体位置"></n-input-number> | |
40 | + </setting-item> | |
41 | + </setting-item-box> | |
42 | + </collapse-item> | |
43 | + <collapse-item name="右侧" :expanded="true"> | |
44 | + <setting-item-box name="是否显示"> | |
45 | + <setting-item name=""> | |
46 | + <n-switch @change="handleChange" v-model:value="optionData.showRight"/> | |
47 | + </setting-item> | |
48 | + </setting-item-box> | |
49 | + <setting-item-box name="文字"> | |
50 | + <setting-item name="字体大小"> | |
51 | + <n-input-number v-model:value="optionData.textRightFontSize" size="small" | |
52 | + placeholder="字体大小"></n-input-number> | |
53 | + </setting-item> | |
54 | + <setting-item name="字体位置x轴"> | |
55 | + <n-input-number v-model:value="optionData.xT" size="small" placeholder="字体位置"></n-input-number> | |
56 | + </setting-item> | |
57 | + <setting-item name="字体位置y轴"> | |
58 | + <n-input-number v-model:value="optionData.yT" size="small" placeholder="字体位置"></n-input-number> | |
59 | + </setting-item> | |
60 | + </setting-item-box> | |
61 | + <setting-item-box name="时间颜色"> | |
62 | + <setting-item name="颜色"> | |
63 | + <n-color-picker size="small" :modes="['hex']" v-model:value="optionData.textRightSizeColor"></n-color-picker> | |
64 | + </setting-item> | |
65 | + </setting-item-box> | |
66 | + </collapse-item> | |
67 | +</template> | |
68 | + | |
69 | +<script setup lang="ts"> | |
70 | +import {PropType, ref} from 'vue' | |
71 | +import {option} from './config' | |
72 | +import { | |
73 | + CollapseItem, | |
74 | + SettingItemBox, | |
75 | + SettingItem | |
76 | +} from '@/components/Pages/ChartItemSetting' | |
77 | +import {SelectOption} from "naive-ui"; | |
78 | + | |
79 | +const props = defineProps({ | |
80 | + optionData: { | |
81 | + type: Object as PropType<typeof option>, | |
82 | + required: true | |
83 | + } | |
84 | +}) | |
85 | + | |
86 | +const selectBgOptions = ref<Array<SelectOption>>([]) | |
87 | + | |
88 | +const selectValue = ref('') | |
89 | + | |
90 | +//TODO待封装 成传文件夹名字获取下面所有图片 | |
91 | +const getFetchImages = () => { | |
92 | + const imagesModules = import.meta.globEager('@/assets/images/chart/headbackground/*') | |
93 | + for (const key in imagesModules) { | |
94 | + selectBgOptions.value.push({ | |
95 | + label: imagesModules[key]?.default.slice(25), | |
96 | + value: imagesModules[key]?.default | |
97 | + }) | |
98 | + } | |
99 | +} | |
100 | +getFetchImages() | |
101 | + | |
102 | +const selectBgValueHandle = (value: string) => { | |
103 | + selectValue.value = value | |
104 | + props.optionData.bgSrc = value | |
105 | +} | |
106 | + | |
107 | +const handleChange = (value: boolean) => { | |
108 | + props.optionData.showRight = value | |
109 | +} | |
110 | +</script> | ... | ... |
1 | +import {ConfigType, PackagesCategoryEnum, ChartFrameEnum} from '@/packages/index.d' | |
2 | +import {ChatCategoryEnum, ChatCategoryEnumName} from '../../index.d' | |
3 | + | |
4 | +export const LeftCenterRightHeadConfig: ConfigType = { | |
5 | + key: 'LeftCenterRightHead', | |
6 | + chartKey: 'VLeftCenterRightHead', | |
7 | + conKey: 'VCLeftCenterRightHead', | |
8 | + title: '通用头部', | |
9 | + category: ChatCategoryEnum.HEADCOMBINATION, | |
10 | + categoryName: ChatCategoryEnumName.HEADCOMBINATION, | |
11 | + package: PackagesCategoryEnum.COMPOSES, | |
12 | + chartFrame: ChartFrameEnum.COMMON, | |
13 | + image: 'left_center_rightHead.png', | |
14 | +} | ... | ... |
1 | +<template> | |
2 | + <div class="go-text-box"> | |
3 | + <n-grid :style="{'background-image': 'url('+option.configOption.bgSrc+')'}" class="go-n-grid" :x-gap="12" :y-gap="3" | |
4 | + :cols="3" layout-shift-disabled> | |
5 | + <n-grid-item> | |
6 | + <!-- 占位--> | |
7 | + <div></div> | |
8 | + </n-grid-item> | |
9 | + <n-grid-item> | |
10 | + <span | |
11 | + style="position:relative" | |
12 | + :style="{ top:option.configOption.y+'px',marginLeft:option.configOption.x+'px',color: option.configOption.textColor, fontSize: option.configOption.fontSize + 'px' }">{{ | |
13 | + option.configOption.dataset | |
14 | + }}</span> | |
15 | + </n-grid-item> | |
16 | + <n-grid-item> | |
17 | + <span style="position:relative" v-if="option.configOption.showRight" | |
18 | + :style="{ top:option.configOption.yT+'px',marginLeft:option.configOption.xT+'px',color: option.configOption.textRightSizeColor, fontSize: option.configOption.textRightFontSize + 'px' }">{{ | |
19 | + newData | |
20 | + }}</span> | |
21 | + </n-grid-item> | |
22 | + </n-grid> | |
23 | + </div> | |
24 | +</template> | |
25 | +<script setup lang="ts"> | |
26 | +import {PropType, toRefs, shallowReactive, watch, onMounted, onUnmounted, ref} from 'vue' | |
27 | +import {CreateComponentType} from '@/packages/index.d' | |
28 | +import {useChartDataFetch} from '@/hooks' | |
29 | +import {useChartEditStore} from '@/store/modules/chartEditStore/chartEditStore' | |
30 | +import {option as configOption} from './config' | |
31 | + | |
32 | +const props = defineProps({ | |
33 | + chartConfig: { | |
34 | + type: Object as PropType<CreateComponentType>, | |
35 | + required: true | |
36 | + } | |
37 | +}) | |
38 | + | |
39 | +const option = shallowReactive({ | |
40 | + configOption | |
41 | +}) | |
42 | + | |
43 | +let yearMonthDay = ref('2021-2-3') | |
44 | + | |
45 | +let nowData = ref('08:00:00') | |
46 | + | |
47 | +let newData = ref('2021-2-3 08:00:00') | |
48 | + | |
49 | +let timer: any = null | |
50 | + | |
51 | +//默认设置宽高距离位置 | |
52 | +props.chartConfig.attr.w = 1920 | |
53 | +props.chartConfig.attr.h = 148 | |
54 | +props.chartConfig.attr.x = 0 | |
55 | +props.chartConfig.attr.y = 0 | |
56 | + | |
57 | +watch( | |
58 | + () => props.chartConfig.option, | |
59 | + (newData: any) => { | |
60 | + option.configOption = newData | |
61 | + }, | |
62 | + { | |
63 | + immediate: true, | |
64 | + deep: false | |
65 | + } | |
66 | +) | |
67 | + | |
68 | +useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { | |
69 | + option.configOption = newData | |
70 | +}) | |
71 | + | |
72 | + | |
73 | +//TODO待封装 这里和原作者时间通用获取当前时间代码一样 | |
74 | +onMounted(() => { | |
75 | +//格式化当前时间 | |
76 | + timer = setInterval(() => { | |
77 | + const | |
78 | + weeks = { | |
79 | + "0": '星期日', | |
80 | + "1": '星期一', | |
81 | + "2": '星期二', | |
82 | + "3": '星期三', | |
83 | + "4": '星期四', | |
84 | + "5": '星期五', | |
85 | + "6": '星期六', | |
86 | + } | |
87 | + const datetime = new Date() | |
88 | + const year = datetime.getFullYear() | |
89 | + const month = datetime.getMonth() + 1 < 10 ? '0' + (datetime.getMonth() + 1) : datetime.getMonth() + 1 | |
90 | + const date = datetime.getDate() < 10 ? '0' + datetime.getDate() : datetime.getDate() | |
91 | + const hh = datetime.getHours() // 时 | |
92 | + const mm = datetime.getMinutes() // 分 | |
93 | + const ss = datetime.getSeconds() // 分 | |
94 | + let weekIndex = datetime.getDay(); | |
95 | + let time = '' | |
96 | + if (hh < 10) time += '0' | |
97 | + time += hh + ':' | |
98 | + if (mm < 10) time += '0' | |
99 | + time += mm + ':' | |
100 | + if (ss < 10) time += '0' | |
101 | + time += ss | |
102 | + yearMonthDay.value = `${year}-${month}-${date}` | |
103 | + nowData.value = time | |
104 | + newData.value = yearMonthDay.value + ' ' + nowData.value + ' ' + weeks[weekIndex] | |
105 | + }, 500) | |
106 | +}) | |
107 | +onUnmounted(() => { | |
108 | + clearInterval(timer) | |
109 | +}) | |
110 | + | |
111 | +</script> | |
112 | + | |
113 | +<style lang="scss" scoped> | |
114 | +@include go('text-box') { | |
115 | + display: flex; | |
116 | + align-items: center; | |
117 | + justify-content: center; | |
118 | + .n-gradient-text { | |
119 | + white-space: initial; | |
120 | + } | |
121 | +} | |
122 | + | |
123 | +.light-green { | |
124 | + height: 108px; | |
125 | + background-color: rgba(0, 128, 0, 0.12); | |
126 | +} | |
127 | + | |
128 | +.green { | |
129 | + height: 108px; | |
130 | + background-color: rgba(0, 128, 0, 0.24); | |
131 | +} | |
132 | + | |
133 | +.go-n-grid { | |
134 | + background: url(@/assets/images/chart/headbackground/bg_top.png) center no-repeat; | |
135 | + background-size: 100% 100%; | |
136 | + text-align: center; | |
137 | + font-size: 36px; | |
138 | + line-height: 90px; | |
139 | +} | |
140 | +</style> | ... | ... |