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