Commit bb25b9df by 饶艳婷

合并分支 'feature/branch_cxr' 到 'develop'

Feature/branch cxr

查看合并请求 !28
parents 5438fc4f 39b37a75
......@@ -34,6 +34,7 @@
"@antv/l7-renderer": "2.15.0",
"@antv/l7-scene": "2.15.0",
"@antv/l7-source": "2.15.0",
"@antv/l7-three": "2.15.0",
"@antv/l7-utils": "2.15.0",
"@antv/s2": "1.35.0",
"@antv/util": "^2.0.17",
......@@ -65,14 +66,17 @@
"lodash.isstring": "^4.0.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"popmotion": "^11.0.5",
"screenfull": "4.2.0",
"sockjs-client": "^1.6.0",
"stompjs": "^2.3.3",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"three": "^0.115.0",
"tinymce": "^5.8.2",
"umy-ui": "^1.1.6",
"vue": "2.6.10",
"vue-amap": "^0.5.10",
"vue-clipboard2": "0.3.1",
"vue-codemirror": "^4.0.6",
"vue-friendly-iframe": "^0.20.0",
......@@ -89,8 +93,7 @@
"vuex": "3.1.0",
"webpack": "^4.46.0",
"xlsx": "^0.17.0",
"xss": "^1.0.14",
"vue-amap": "^0.5.10"
"xss": "^1.0.14"
},
"devDependencies": {
"@babel/core": "^7.4.0-0",
......
......@@ -1371,6 +1371,7 @@ export default {
table_column_custom: '自定义',
chart_table_pivot: '透视表',
chart_heat_map: '热力图',
chart_building: '点击建筑',
chart_3d_column_chart_map: '3D柱图',
table_pivot_row: '数据行',
field_error_tips: '该字段所对应的数据集原始字段发生变更(包括维度、指标,字段类型,字段被删除等),建议重新编辑',
......
import { getLabel, getLegend, getPadding, getTheme, getTooltip, getXAxis } from '@/views/chart/chart/common/common_antv'
import { antVCustomColor } from '@/views/chart/chart/util'
import { Scene } from '@antv/l7'
import { GaodeMap } from '@antv/l7-maps'
import { ThreeLayer, ThreeRender } from '@antv/l7-three'
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { animate, easeInOut } from 'popmotion'
export function baseBuildingOptionAntV(scene, container, chart, action) {
function changeValue(
startValue,
endValue,
duration = 500,
callback,
complete
) {
if (typeof startValue === 'number') {
animate({
from: {
v: startValue
},
to: {
v: endValue
},
ease: easeInOut,
duration,
onUpdate: o => {
callback(o.v)
return ''
},
onComplete: () => {
complete && complete()
return ''
}
})
} else {
animate({
from: {
lng: startValue.lng,
lat: startValue.lat,
pitch: startValue.pitch,
rotation: startValue.rotation,
zoom: startValue.zoom
},
to: {
lng: (endValue).lng,
lat: (endValue).lat,
pitch: (endValue).pitch,
rotation: (endValue).rotation,
zoom: (endValue).zoom
},
ease: easeInOut,
duration,
onUpdate: o => {
callback(o)
return ''
},
onComplete: () => {
complete && complete()
return ''
}
})
}
return ''
}
const raycaster = new THREE.Raycaster()
const lng = 120.1
const lat = 30.265
scene = new Scene({
id: container,
map: new GaodeMap({
center: [lng, lat],
pitch: 70,
rotation: 220,
zoom: 16,
}),
logoVisible: false
})
scene.on('loaded', () => {
const mouse = new THREE.Vector2()
let zspace,
aspace,
ASpaceTextMesh,
ZSpaceTextMesh
scene.registerRenderService(ThreeRender)
const center = scene.getCenter()
const threeJSLayer = new ThreeLayer({
enableMultiPassRenderer: false,
// @ts-ignore
onAddMeshes: (threeScene, layer) => {
threeScene.add(new THREE.AmbientLight(0xffffff))
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25)
sunlight.position.set(0, 80000000, 100000000)
sunlight.matrixWorldNeedsUpdate = true
threeScene.add(sunlight)
// map
// https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ
// height
// https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ
const image = new Image()
image.crossOrigin = ''
image.src =
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ'
image.onload = () => {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0, image.width, image.height)
const heightData = ctx.getImageData(0, 0, image.width, image.height)
.data
const s = 53000
const geometry = new THREE.PlaneGeometry(s, s, 255, 255)
geometry.vertices.map((v, i) => {
const r = heightData[i * 4]
const g = heightData[i * 4 + 1]
const b = heightData[i * 4 + 2]
let h =
-10000.0 +
(r * 255.0 * 256.0 * 256.0 + g * 255.0 * 256.0 + b * 255.0) *
0.1
h = h / 20 - 127600
h = Math.max(0, h)
v.z = h
return ''
})
const material = new THREE.MeshPhongMaterial({
transparent: true,
// opacity: 0.6,
map: new THREE.TextureLoader().load(
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ'
),
side: THREE.DoubleSide
})
const plane = new THREE.Mesh(geometry, material)
layer.setObjectLngLat(plane, [120.1008, 30.2573], 0)
plane.position.z = 10
threeScene.add(plane)
return ''
}
// 使用 Three.js glTFLoader 加载模型
const loader = new GLTFLoader()
loader.load(
'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
gltf => {
const antModel = gltf.scene
setDouble(antModel)
// antModel.children[0].material.side = THREE.DoubleSide
layer.adjustMeshToMap(antModel)
layer.setMeshScale(antModel, 20, 20, 20)
layer.setObjectLngLat(
antModel,
[center.lng - 0.002, center.lat],
0
)
const animations = gltf.animations
if (animations && animations.length) {
const mixer = new THREE.AnimationMixer(antModel)
const animation = animations[1]
const action = mixer.clipAction(animation)
action.play()
layer.addAnimateMixer(mixer)
}
antModel.rotation.y = Math.PI
// 向场景中添加模型
threeScene.add(antModel)
// 重绘图层
layer.render()
return ''
}
)
const v = `
varying vec2 vUv;
varying vec4 worldPosition;
void main() {
vUv = uv;
worldPosition = modelMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`
const f = `
varying vec2 vUv;
varying vec4 worldPosition;
uniform vec3 color;
void main() {
gl_FragColor = vec4(color, fract(worldPosition.z / 50.0));
}`
const shadermaterial = new THREE.ShaderMaterial({
uniforms: {
color: {
value: new THREE.Vector3(0.21372549, 0.34705882, 0.56470588)
}
},
vertexShader: v,
fragmentShader: f,
side: THREE.DoubleSide
})
const fbxLoaded = new FBXLoader()
// load ZSpace
fbxLoaded.load(
'https://gw.alipayobjects.com/os/bmw-prod/af1652c9-3c4f-4e73-ac4c-1f78fefbaf6a.fbx',
gltf => {
zspace = gltf
layer.adjustMeshToMap(zspace)
// @ts-ignore
zspace.children[0].material = shadermaterial
layer.setMeshScale(zspace, 10, 10, 10)
layer.setObjectLngLat(zspace, [120.1015, 30.2661], 0)
zspace.rotation.x = Math.PI * 2
zspace.rotation.z = -Math.PI * (-2 / 15)
threeScene.add(zspace)
return ''
}
)
fbxLoaded.load(
'https://gw.alipayobjects.com/os/bmw-prod/11d6e4c1-bd5b-4dc1-bae5-ac51c14e9056.fbx',
model => {
aspace = model
layer.adjustMeshToMap(aspace)
// @ts-ignore
aspace.children[0].material = shadermaterial
layer.setMeshScale(aspace, 8, 8, 8)
layer.setObjectLngLat(aspace, [120.099, 30.261], 0)
aspace.rotation.x = Math.PI * 2
aspace.rotation.z = -Math.PI * (3 / 15)
threeScene.add(aspace)
return ''
}
)
const textLoader = new THREE.FontLoader()
textLoader.load(
'https://gw.alipayobjects.com/os/bmw-prod/0a3f46eb-294e-4d95-87f2-052c26ad4bf1.json',
font => {
const fontOptions = {
size: 360, // 字号大小,一般为大写字母的高度
height: 50, // 文字的厚度
font, // 字体,默认是'helvetiker',需对应引用的字体文件
bevelThickness: 10, // 倒角厚度
bevelSize: 10, // 倒角宽度
curveSegments: 30, // 弧线分段数,使得文字的曲线更加光滑
bevelEnabled: true // 布尔值,是否使用倒角,意为在边缘处斜切
}
const aspaceGeo = new THREE.TextGeometry('ASpace', fontOptions)
aspaceGeo.center()
const zspaceGeo = new THREE.TextGeometry('ZSpace', fontOptions)
zspaceGeo.center()
const fontMat = new THREE.MeshPhongMaterial({
color: 0xcccccc,
shininess: 60,
specular: 0xcccccc,
side: THREE.DoubleSide
})
const testHeight = 900
ASpaceTextMesh = new THREE.Mesh(aspaceGeo, fontMat)
ASpaceTextMesh.rotation.x = Math.PI / 2
ASpaceTextMesh.rotation.y = (-Math.PI * 3) / 4
layer.setObjectLngLat(
ASpaceTextMesh,
[120.099, 30.261],
testHeight
)
threeScene.add(ASpaceTextMesh)
ZSpaceTextMesh = new THREE.Mesh(zspaceGeo, fontMat)
ZSpaceTextMesh.rotation.x = Math.PI / 2
ZSpaceTextMesh.rotation.y = (-Math.PI * 3) / 4
layer.setObjectLngLat(
ZSpaceTextMesh,
[120.103, 30.2661],
testHeight
)
threeScene.add(ZSpaceTextMesh)
getH(0, 200)
function getH(h1, h2) {
changeValue(
h1,
h2,
1000,
h => {
ASpaceTextMesh.position.z = testHeight + h
ZSpaceTextMesh.position.z = testHeight + h
return ''
},
() => {
setTimeout(() => getH(h2, h1), 10)
return ''
}
)
}
return ''
}
)
}
})
.animate(true)
scene.addLayer(threeJSLayer)
// @ts-ignore
let currentCamera = threeJSLayer.threeRenderService?.getRenderCamera()
const currentView = {
lng: center.lng,
lat: center.lat,
pitch: 70,
rotation: 220,
zoom: 16
}
scene.on('zoom', () => {
const cen = scene.getCenter()
currentView.lng = cen.lng
currentView.lat = cen.lat
currentView.pitch = scene.getPitch()
currentView.zoom = scene.getZoom()
return ''
})
scene.map.on('mapchange', () => {
// @ts-ignore
currentCamera = threeJSLayer.getRenderCamera()
currentView.pitch = scene.getPitch()
return ''
})
const ASpaceView = {
lng: 120.109509,
lat: 30.251529,
pitch: 83,
rotation: 225,
zoom: 15
}
const ZSpaceView = {
lng: 120.112026,
lat: 30.256881,
pitch: 80,
rotation: 220,
zoom: 15
}
scene.on('click', ev => {
// @ts-ignore
const size = scene?.map?.getSize()
mouse.x = (ev.pixel.x / size.width) * 2 - 1
mouse.y = -(ev.pixel.y / size.height) * 2 + 1
raycaster.setFromCamera(mouse, currentCamera)
const intersects = raycaster.intersectObjects([zspace, aspace], true)
if (intersects.length > 0) {
const object = intersects[0].object
if (object.name === 'Z空间') {
selectSpace(currentView, ZSpaceView, ZSpaceTextMesh)
} else {
selectSpace(currentView, ASpaceView, ASpaceTextMesh)
}
}
return ''
})
function selectSpace(
currentView,
targetView,
spaceText
) {
if (spaceText) {
changeValue(
spaceText.rotation.y,
spaceText.rotation.y + Math.PI * 2,
500,
r => {
spaceText.rotation.y = r
return ''
}
)
}
changeValue(currentView, targetView, 500, view => {
scene.setCenter([view.lng, view.lat])
scene.setPitch(view.pitch)
scene.setRotation(view.rotation)
scene.setZoom(view.zoom)
currentView.lng = view.lng
currentView.lat = view.lat
currentView.pitch = view.pitch
currentView.rotation = view.rotation
currentView.zoom = view.zoom
return ''
})
}
return ''
})
function setDouble(object) {
if (object.children && object.children.length && object.children.length > 0) {
object.children.map(child => setDouble(child))
} else if (object.material) {
object.material.side = THREE.DoubleSide
}
}
// 开始渲染
if (scene) {
scene.destroy()
}
return scene
}
......@@ -2180,6 +2180,40 @@ export const TYPE_CONFIGS = [
]
}
},
// 点击建筑
{
render: 'antv',
category: 'chart.chart_type_space',
value: 'chart_building',
title: 'chart.chart_building',
icon: 'building',
properties: [
'color-selector',
'size-selector-ant-v',
'title-selector-ant-v'
],
propertyInner: {
'color-selector': [
'mapStyle'
],
'size-selector-ant-v': [
'mapPitch'
],
'title-selector-ant-v': [
'show',
'title',
'fontSize',
'color',
'hPosition',
'isItalic',
'isBolder',
'remarkShow',
'fontFamily',
'letterSpace',
'fontShadow'
]
}
},
/* 下面是echarts图表类型 */
{
render: 'echarts',
......
......@@ -68,6 +68,8 @@ import { baseCityBrightnessMapOptionAntV } from '@/views/chart/chart/cityBrightn
import { baseCitySweepMapOptionAntV } from '@/views/chart/chart/citySweep/citySweep_antv'
import { clear } from 'size-sensor'
import { baseSankeyOptionAntV } from '@/views/chart/chart/sankey/sankey_antv'
import { baseBuildingOptionAntV } from '@/views/chart/chart/building/building'
export default {
name: 'ChartComponentG2',
components: { TitleRemark, ViewTrackBar, ChartTitleUpdate },
......@@ -263,6 +265,7 @@ export default {
]
}
}
console.log('chart.type ',chart.type )
if (chart.type === 'bar') {
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
} else if (chart.type === 'bar-group') {
......@@ -313,12 +316,17 @@ export default {
this.myChart = baseBubbleMapOption(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'city-brightness') {
this.myChart = baseCityBrightnessMapOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'city-sweep') {
this.myChart = baseCitySweepMapOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'chart_sankey') {
this.myChart = baseSankeyOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'threeDColumn') {
this.myChart = base3DColumnOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else if (chart.type === 'chart_building') {
this.myChart = baseBuildingOptionAntV(this.myChart, this.chartId, chart, this.antVAction)
} else {
if (this.myChart) {
this.antVRenderStatus = false
......
......@@ -42,7 +42,17 @@ module.exports = {
filename: 'index.html'
}
},
configureWebpack: {
module: {
rules: [
{
test: /\.mjs$/,
include: /node_modules/,
type: 'javascript/auto'
}
]
},
name: name,
devtool: 'source-map',
resolve: {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论