This commit is contained in:
ann 2023-03-31 17:33:52 +08:00
parent e06deda6bc
commit f650435718
6 changed files with 1019 additions and 401 deletions

BIN
public/blue_line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

BIN
public/green_line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/red_line.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -3,16 +3,16 @@
<div id="earth" />
<transition name="el-zoom-in-bottom">
<div v-show="!globe&&cp" class="chinaDetail">
<el-button :class="activeTab === 'ys' ? 'active':''" @click="filterData('ys')">云算中心 {{ ys.length }}</el-button>
<el-button :class="activeTab === 'ys' ? 'active':''" @click="filterData('ys')"><svg-icon icon-class="ys" />云算中心 {{ ys.length }}</el-button>
<el-button :class="activeTab === 'zs' ? 'active':''" @click="filterData('zs')"><svg-icon icon-class="zs" />智算中心 {{ zs.length }}</el-button>
<el-button :class="activeTab === 'cs' ? 'active':''" @click="filterData('cs')"><svg-icon icon-class="cs" />超算中心 {{ cs.length }}</el-button>
<el-button :class="activeTab === 'dsxs' ? 'active':''" @click="filterData('dsxs')"><svg-icon icon-class="dsxs" />东数西算 {{ dsxs.length }}</el-button>
<!-- <el-button :class="activeTab === 'dsxs' ? 'active':''" @click="filterData('dsxs')"><svg-icon icon-class="dsxs" />东数西算 {{ dsxs.length }}</el-button> -->
<p v-for="(it,ind) in connectionStateMap" :key="ind"><svg-icon :icon-class="connectionStateSVG[ind]" />{{ it + ':' +connectionState[ind] }}</p>
</div>
</transition>
<div v-show="!globe" class="switchDataBtn">
<el-button :class="cp?'active':''" @click="switchData(true)">算力网</el-button>
<el-button :class="!cp?'active':''" @click="switchData(false)">新型网络</el-button>
<el-button :class="!cp?'active':''" @click="switchData(false)">新型枢纽</el-button>
</div>
<a class="switchBtn toChina" :class="!globe?'activeBtn':''" @click="toChina"><svg-icon icon-class="china" /></a>
<a class="switchBtn" :class="globe?'activeBtn':''" @click="toWorld"><svg-icon icon-class="globe" /></a>
@ -20,15 +20,15 @@
</template>
<script>
import * as Three from 'three'
import proj4 from 'proj4'
import { getPosition, transformToLatLon } from '@/utils/earth-calcu'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { originEarthRegion, getEarthDetails } from '@/api/top-menu/TotalNum'
import { getEarthRegion } from '@/api/top-menu/TotalNum'
import chinaJson from './chinaProvince.json'
import borderJson from './border.json'
import continentsJson from './worldContinents.json'
import countingJson from './counting.json'
// import countingJson from './counting.json'
import TWEEN from '@tweenjs/tween.js'
import { MeshLine, MeshLineMaterial } from 'three.meshline'
import { MeshLine, MeshLineMaterial } from './threemeshline'
import {
createFlyCurve, timerFlyCurve
} from './flyCurve.js'
@ -36,7 +36,7 @@ import {
export default {
data() {
return {
mshs: 1.0,
mshs: 0.8,
satellitesArr: [],
mapMarks: [],
area: [],
@ -101,39 +101,26 @@ export default {
},
methods: {
getEarth() {
originEarthRegion().then(res => {
const demo = res.data
const that = this
this.ys = res.data
for (let i = 0; i < 6; i++) {
const modelItem = []
const value = []
modelItem['name'] = demo[i].area
modelItem['count'] = demo[i].areaCount
value[0] = demo[i].value[0]
value[1] = demo[i].value[1]
modelItem['value'] = value
that.mapMarks[i] = modelItem
}
})
getEarthDetails('杭州').then(res => {
const demo = res.data
const that = this
that.area['resourceArea'] = demo.resourceArea
that.area['userNum'] = demo.userNum
that.area['areaCount'] = demo.areaCount
that.area['clusterNum'] = demo.clusterNum
that.area['usagedRate'] = demo.usagedRate
})
this.zs = []
this.cs = []
this.dsxs = []
countingJson.forEach(ele => {
this.connectionState[ele.connectionState]++
if (ele.name.indexOf('集群') > -1) { this.dsxs.push(ele) } else {
ele.name.indexOf('超算') > -1 ? this.cs.push(ele) : this.zs.push(ele)
}
getEarthRegion().then(res => {
this.zs = []
this.cs = []
this.ys = []
this.dsxs = []
this.mapMarks = []
res.data.centers.forEach(ele => {
if (ele.area === '中国') {
if (ele.type === '云算资源' && ele.centerSource === 'nudt') {
this.ys.push(ele)
} else {
ele.type === '超算资源' ? this.cs.push(ele) : this.zs.push(ele)
}
this.connectionState[ele.connectionState]++
} else {
// if (ele.centerSource === '') {
this.mapMarks.push(ele)
// }
}
})
})
},
filterData(type) {
@ -144,7 +131,7 @@ export default {
this.scene.getObjectByName('ys').visible = false
this.scene.getObjectByName('zs').visible = false
this.scene.getObjectByName('cs').visible = false
this.scene.getObjectByName('dsxs').visible = false
// this.scene.getObjectByName('dsxs').visible = false
this.scene.getObjectByName(this.activeTab).visible = true
},
switchData(type) {
@ -155,18 +142,18 @@ export default {
ele.visible = false
})
this.cp = !this.cp
this.scene.getObjectByName('chinaPointLine').visible = !this.cp
this.scene.getObjectByName('earthLine').visible = this.cp
this.scene.getObjectByName('point').visible = !this.cp
this.scene.getObjectByName('pointText').visible = !this.cp
this.scene.getObjectByName('zs').visible = this.cp
this.scene.getObjectByName('ys').visible = false
this.scene.getObjectByName('cs').visible = false
this.scene.getObjectByName('dsxs').visible = false
// this.scene.getObjectByName('dsxs').visible = false
},
toWorld() {
if (this.globe === true) return false
this.globe = true
this.scene.getObjectByName('chinaPointLine').visible = false
this.scene.getObjectByName('earthLine').visible = true
this.scene.getObjectByName('point').visible = false
var s = 140
this.camera.zoom = 1
@ -175,25 +162,20 @@ export default {
this.scene.getObjectByName('earth').material.color.copy(new Three.Color())
this.scene.getObjectByName('earth-cloud').visible = true
this.scene.getObjectByName('earth').material.map = this.worldMapTexture
this.scene.getObjectByName('chinaProvince').visible = false
this.resetVisible()
})
// const tweenL2 = new TWEEN.Tween(this.camera.position).to({ x: this.originPosition.x, y: this.originPosition.y, z: this.originPosition.z }, 1800).easing(TWEEN.Easing.Sinusoidal.InOut)
// .onUpdate(() => {
// this.camera.position.set({ x: -400, y: 400, z: 1700 }, 1800)
// })
// tweenL2.start()
tweenL1.start()
this.zoomAnimate()
this.orbitControls.reset()
this.orbitControls.autoRotate = true
// })
this.render()
},
resetVisible() {
this.scene.getObjectByName('globeAreaMark').visible = this.globe
// this.scene.getObjectByName('globeAreaMark').visible = this.globe
this.scene.getObjectByName('globePoint').visible = this.globe
this.scene.getObjectByName('globePointText').visible = this.globe
// this.scene.getObjectByName('globePointText').visible = this.globe
this.activeTab = 'zs'
this.scene.getObjectByName('zs').visible = !this.globe
this.camera.lookAt(this.scene.position)
@ -214,55 +196,65 @@ export default {
this.camera.position).to({ x: -300, y: 300, z: 1700 }, 1800)
.easing(TWEEN.Easing.Sinusoidal.InOut)
const tweenL2 = new TWEEN.Tween(this.camera).to({ left: -s * this.k, right: s * this.k, top: s, bottom: -s }, 1000).easing(TWEEN.Easing.Sinusoidal.InOut)
// .onUpdate(() => {
// // this.camera.zoom = 2.3
// // this.scene.children[5].material.color.copy(new Three.Color(0x0a263e))
// })
const tweenL3 = new TWEEN.Tween(this.scene.getObjectByName('earth').material.color).to(new Three.Color(0x0a263e80), 1000).easing(TWEEN.Easing.Sinusoidal.InOut)
.onUpdate(() => {
this.scene.getObjectByName('earth-cloud').visible = false
this.scene.getObjectByName('earth').material.map = this.chinaMapTexture
this.scene.getObjectByName('chinaProvince').visible = true
})
// const tweenL4 = new TWEEN.Tween(this.scene.getObjectByName('chinaProvince').material.color).to(new Three.Color(0x0a263e80), 1000).easing(TWEEN.Easing.Sinusoidal.InOut)
this.scene.getObjectByName('chinaProvince').children.forEach(ele => {
ele.children[0].material.color = new Three.Color(0x0a315ab8)
})
// const tweenL4 = new TWEEN.Tween(this.scene.getObjectByName('chinaProvince').material.color).to(new Three.Color(0x0a263e80), 1000).easing(TWEEN.Easing.Sinusoidal.InOut)
// this.scene.getObjectByName('chinaProvince').children.forEach(ele => {
// ele.children[0].material.color = new Three.Color(0x0a315ab8)
// })
tweenL1.chain(tweenL2).start()
tweenL3.start()
// tweenL4.start()
},
renderChinaDetailData() {
const groupLines = new Three.Group()
groupLines.name = 'chinaPointLine'
groupLines.name = 'earthLine'
const center = {
name: '鹏城云脑',
longitude: 114.057868,
latitude: 22.543099
}
this.mapMarks.forEach(r => {
if (this.mapMarks[0].value[0] !== r.value[0]) {
var i = this.lineConnect(this.mapMarks[0].value, r.value)
groupLines.add(i)
}
var i = this.globalLineConnect([center.longitude, center.latitude], [r.longitude, r.latitude])
groupLines.add(i)
})
this.ys = this.mapMarks.map(ele => { return { name: ele.name, coordinate: ele.value } })
// this.ys = this.mapMarks.map(ele => { return { name: ele.name, coordinate: ele.value } })
this.scene.add(groupLines)
this.setChinaMark(this.mapMarks)
this.setCpPoint('ys')
this.setCpPoint('zs')
this.setCpPoint('cs')
this.setCpPoint('dsxs')
this.scene.getObjectByName('chinaPointLine').visible = false
// this.setCpPoint('dsxs')
// this.scene.getObjectByName('earthLine').visible = true
this.scene.getObjectByName('point').visible = false
this.scene.getObjectByName('pointText').visible = false
},
globalLineConnect(posStart, posEnd) {
const p1 = getPosition(posStart[0] + 90, posStart[1], 100.01)
const p2 = getPosition(posEnd[0] + 90, posEnd[1], 100.01)
const pmiddle = getPosition((posStart[0] + posEnd[0]) / 2 + 90, (posStart[1] + posEnd[1]) / 2, 150)
var points = [
new Three.Vector3(p1.x, p1.y, p1.z),
new Three.Vector3(pmiddle.x, pmiddle.y, pmiddle.z),
new Three.Vector3(p2.x, p2.y, p2.z)
]
return createFlyCurve(points, false)
// this.scene.add(flyLine)
},
setCpPoint(type) {
// const zsp = this.
const mark = new Three.Group()
mark.name = type
const textMark = new Three.Group()
textMark.name = type + 'Text'
this[type].forEach(ele => {
var markPos = this.getPosition(ele.coordinate[0] + 90, ele.coordinate[1], 100)
var markPos = getPosition(ele.longitude + 90, ele.latitude, 100)
var textureLoader = new Three.TextureLoader()
var mesh = new Three.Sprite(
new Three.SpriteMaterial({
map: textureLoader.load(process.env.VUE_APP_PUBLIC_SOURCE_API + '/' + (type === 'ys' ? 'statusEnd' : this.connectionStateSVG[ele.connectionState]) + '.svg'),
map: textureLoader.load(process.env.VUE_APP_PUBLIC_SOURCE_API + '/' + this.connectionStateSVG[ele.connectionState] + '.svg'),
transparent: true,
depthWrite: false
})
@ -273,8 +265,7 @@ export default {
mesh.position.set(markPos.x, markPos.y, markPos.z)
mark.add(mesh)
//
var texture = new Three.CanvasTexture(this.getCanvasFont(ele.name))
var texture = new Three.CanvasTexture(this.getChinaFont(ele.name))
//
const fontNumber = ele.name.length * 10 + 10 + 2.4072265625 + 5
texture.needsUpdate = true
@ -285,8 +276,7 @@ export default {
)
fontMesh.scale.x = fontNumber / 5
fontMesh.scale.y = 3
fontMesh.center = new Three.Vector2(0, 0)
fontMesh.position.set(markPos.x - 1, markPos.y, markPos.z)
fontMesh.position.set(markPos.x - 1, markPos.y - 0.5, markPos.z - 2)
textMark.add(fontMesh)
})
mark.visible = false
@ -303,7 +293,7 @@ export default {
var mark = new Three.Mesh(new Three.SphereGeometry(0.5), new Three.MeshBasicMaterial({
color: '#FFFFFF'
}))
var markPos = this.getPosition(_markData[i].value[0] + 90, _markData[i].value[1], 100)
var markPos = getPosition(_markData[i].longitude + 90, _markData[i].latitude, 100)
mark.position.set(markPos.x, markPos.y, markPos.z)
marking.add(mark)
@ -325,195 +315,104 @@ export default {
this.scene.add(textMarking)
},
lineConnect(posStart, posEnd) {
const p1 = this.getPosition(posStart[0] + 90, posStart[1], 100.01)
const p2 = this.getPosition(posEnd[0] + 90, posEnd[1], 100.01)
const pmiddle = this.getPosition((posStart[0] + posEnd[0]) / 2 + 90, (posStart[1] + posEnd[1]) / 2, 110)
var points = [
// 3D z
const p1 = getPosition(posStart[0] + 90, posStart[1], 100.01)
const p2 = getPosition(posEnd[0] + 90, posEnd[1], 100.01)
const pmiddle = getPosition((posStart[0] + posEnd[0]) / 2 + 90, (posStart[1] + posEnd[1]) / 2, 160)
// 使QuadraticBezierCurve3() 线
const curve = new Three.CubicBezierCurve3(
new Three.Vector3(p1.x, p1.y, p1.z),
new Three.Vector3(pmiddle.x, pmiddle.y, pmiddle.z),
new Three.Vector3(p2.x, p2.y, p2.z)
]
return createFlyCurve(points, false)
// this.scene.add(flyLine)
},
// lineConnect(posStart, posEnd) {
// // 3D z
// const p1 = this.getPosition(posStart[0] + 90, posStart[1], 100.01)
// const p2 = this.getPosition(posEnd[0] + 90, posEnd[1], 100.01)
// const pmiddle = this.getPosition((posStart[0] + posEnd[0]) / 2 + 90, (posStart[1] + posEnd[1]) / 2, 110)
)
// // 使QuadraticBezierCurve3() 线
// const curve = new Three.QuadraticBezierCurve3(
// new Three.Vector3(p1.x, p1.y, p1.z),
// // new Three.Vector3((p1.x + p2.x) / 2, (p1.y + p2.y) / 2 + 2, (p1.z + p2.z) / 2),
// new Three.Vector3(pmiddle.x, pmiddle.y, pmiddle.z),
// new Three.Vector3(p2.x, p2.y, p2.z)
// )
// // console.log(curve)
// //
// // spotCircle([x0, y0, z0])
// // spotCircle([x1, y1, z1])
// const lineGeometry = new Three.BufferGeometry()
// var curve2 = new Three.CatmullRomCurve3(curve.getPoints(50), false)
// console.log(curve2)
// // 线 50
// var points = curve2.points
// var positions = []
// var index = []
// // var colors = []
// // var color = new Three.Color()
// points.forEach((elem, idx) => {
// positions.push(elem.x, elem.y, elem.z)
// index.push(idx)
// })
// // //
// // lineGeometry.setAttribute('position', new Three.BufferAttribute(new Float32Array(positions), 3, true))
// // lineGeometry.setAttribute('color', new Three.BufferAttribute(new Float32Array(colors), 3, true))
// lineGeometry.setAttribute('position', new Three.Float32BufferAttribute(positions, 3))
// lineGeometry.setAttribute('u_index', new Three.Float32BufferAttribute(index, 1))
// console.log(lineGeometry)
// const mesh = new Three.Mesh(lineGeometry, this.flylineMaterial())
// console.log(mesh)
// mesh.name = 'fly'
// // mesh._flyId = 0
// mesh._speed = 1
// mesh._repeat = 1
// mesh._been = 0
// mesh._total = curve2.length
// // mesh._callback = callback
// this.flyId++
// this.flyArr.push(mesh)
// return mesh
// },
flylineMaterial() {
const colorArr = this.getColorArr('rgba(255,255,255,1)')
this.flyShader = {
vertexshader: `
uniform float size;
uniform float time;
uniform float u_len;
attribute float u_index;
varying float u_opacitys;
void main() {
if( u_index < time + u_len && u_index > time){
float u_scale = 1.0 - (time + u_len - u_index) /u_len;
u_opacitys = u_scale;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
gl_PointSize = size * u_scale * 300.0 / (-mvPosition.z);
}
}
`,
fragmentshader: `
uniform sampler2D u_map;
uniform float u_opacity;
uniform vec3 color;
uniform float isTexture;
varying float u_opacitys;
void main() {
vec4 u_color = vec4(color,u_opacity * u_opacitys);
if( isTexture != 0.0 ){
gl_FragColor = u_color * texture2D(u_map, vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y));
}else{
gl_FragColor = u_color;
}
}`
const lineGeometry = new Three.BufferGeometry()
// 线 50
var points = curve.getPoints(50)
var positions = []
// //
for (var j = 0; j < points.length; j++) {
// color.setHSL( .31666+j*0.005,0.7, 0.7); //绿
// color.setHSL(0.81666 + j, 0.88, 0.715 + j * 0.0025) //
// colors.push(color.r, color.g, color.b)
positions.push(points[j].x, points[j].y, points[j].z)
}
const texture = new Three.TextureLoader().load(process.env.VUE_APP_PUBLIC_SOURCE_API + '/point.png')
const material = new Three.ShaderMaterial({
uniforms: {
color: {
value: colorArr[0],
type: 'v3'
},
size: {
value: 1, // width,
type: 'f'
},
u_map: {
value: texture,
type: 't2'
},
u_len: {
value: length,
type: 'f'
},
u_opacity: {
value: colorArr[1],
type: 'f'
},
time: {
value: -10, // length,
type: 'f'
},
isTexture: {
value: 1.0,
type: 'f'
}
},
transparent: false,
depthTest: true,
vertexShader: this.flyShader.vertexshader,
fragmentShader: this.flyShader.fragmentshader
// //
lineGeometry.setAttribute('position', points)
// lineGeometry.setAttribute('color', new Three.BufferAttribute(new Float32Array(colors), 3, true))
const meshLine = new MeshLine()
meshLine.setGeometry(lineGeometry)
const defaultOptions = {
speed: 0.3,
lineWidth: 1,
length: 0.3,
isHalf: false,
lineColor: 'rgba(225,225,0,0.2)',
lightColor: 'rgba(225,225,0,1)',
duration: 1000,
delay: 0,
repeat: Infinity
}
const getTexture = (length, lineColor, lightColor, isHalf) => {
const canvas = document.createElement('canvas')
canvas.width = 256
canvas.height = 1
const ctx = canvas.getContext('2d')
const gradient = ctx.createLinearGradient(0, 0, 256, 1)
gradient.addColorStop(0, lineColor)
gradient.addColorStop(isHalf ? length : length / 2, lightColor)
gradient.addColorStop(length, lineColor)
gradient.addColorStop(length, lineColor)
gradient.addColorStop(1, lineColor)
ctx.fillStyle = gradient
ctx.fillRect(0, 0, 256, 1)
const texture = new Three.Texture(canvas)
texture.needsUpdate = true
texture.wrapS = Three.RepeatWrapping
texture.wrapT = Three.RepeatWrapping
return texture
}
const texture = getTexture(defaultOptions.length, defaultOptions.lineColor, defaultOptions.lightColor, defaultOptions.isHalf)
// const texture = new Three.TextureLoader().load(process.env.VUE_APP_PUBLIC_SOURCE_API + '/green_line.png')
texture.anisotropy = 16
texture.wrapS = Three.RepeatWrapping
texture.wrapT = Three.RepeatWrapping
// const color = new Three.Color()
this.dynamicMaterial = new MeshLineMaterial({
useMap: 1, //
// color: new Three.Color(0x006666),
opacity: 1,
resolution: new Three.Vector2(window.innerWidth, window.innerHeight),
sizeAttenuation: 1,
lineWidth: 0.003,
transparent: true,
// useDash: 1,
// wireframe: true,
dashArray: 0,
dashRatio: 0.1,
dashOffset: 0, //
// blending: Three.AdditiveBlending,
// repeat: new Three.Vector2(2, 1),
map: texture
})
return material
},
flyAnimation(delta = 0.015) {
TWEEN.update()
if (delta > 0.2) return
this.flyArr.forEach(elem => {
if (!elem.parent) return
if (elem._been > elem._repeat) {
elem.visible = false
// if (typeof elem._callback === 'function') {
// elem._callback(elem)
// }
// this.remove(elem)
} else {
const uniforms = elem.material.uniforms
//
if (uniforms.time.value < elem._total) {
uniforms.time.value += delta * (this.baicSpeed / delta) * elem._speed
} else {
elem._been += 1
uniforms.time.value = -uniforms.u_len.value
}
}
})
},
getColorArr(str) {
if (Array.isArray(str)) return str // error
var _arr = []
str = str + ''
str = str.toLowerCase().replace(/\s/g, '')
if (/^((?:rgba)?)\(\s*([^\)]*)/.test(str)) {
var arr = str.replace(/rgba\(|\)/gi, '').split(',')
var hex = [
pad2(Math.round(arr[0] * 1 || 0).toString(16)),
pad2(Math.round(arr[1] * 1 || 0).toString(16)),
pad2(Math.round(arr[2] * 1 || 0).toString(16))
]
_arr[0] = new Three.Color('#' + hex.join(''))
_arr[1] = Math.max(0, Math.min(1, (arr[3] * 1 || 0)))
} else if (str === 'transparent') {
_arr[0] = new Three.Color()
_arr[1] = 0
} else {
_arr[0] = new Three.Color(str)
_arr[1] = 1
}
function pad2(c) {
return c.length === 1 ? '0' + c : '' + c
}
return _arr
this.flyLineAnimate()
// const { width, height } = getCanvasSize()
// material.uniforms.resolution.value.set(width, height)
const mesh = new Three.Mesh(meshLine.geometry, this.dynamicMaterial)
return mesh
},
flyLineAnimate() {
requestAnimationFrame(this.flyLineAnimate)
if (this.dynamicMaterial) {
this.dynamicMaterial.uniforms.offset.value.x -= 0.005
this.dynamicMaterial.uniforms.dashOffset.value -= 0.005
}
},
@ -591,7 +490,7 @@ export default {
this.scene.add(this.mesh) // 5
this.scene.add(this.mesh2) // 6
this.setMark(this.mapMarks) //
this.setAreaMark(this.area)
// this.setAreaMark(this.area)
// this.scene.rotation.z = Math.PI / 10
this.scene.rotation.x = Math.PI / 20
this.scene.rotation.y = -500
@ -632,11 +531,11 @@ export default {
const coordinates = elem.geometry.coordinates
coordinates.forEach(multiPolygon => {
multiPolygon.forEach(polygon => {
const lineMaterial = new Three.LineBasicMaterial({ color: 0x3EDFFC })
const lineMaterial = new Three.LineBasicMaterial({ color: 0x0a315ab8 })
const positions = []
const lineGeometry = new Three.BufferGeometry()
for (let i = 0; i < polygon.length; i++) {
var pos = this.getPosition(polygon[i][0] + 90, polygon[i][1], 100)
var pos = getPosition(polygon[i][0] + 90, polygon[i][1], 100)
if (pos.x) {
positions.push(pos.x, pos.y, pos.z)
} else {
@ -651,6 +550,7 @@ export default {
})
map.add(province)
})
map.visible = false
this.scene.add(map)
const mapBorder = new Three.Group()
mapBorder.name = 'chinaBorder'
@ -660,18 +560,19 @@ export default {
multiPolygon.forEach(polygon => {
// const lineMaterial = new Three.LineBasicMaterial({ color: 0x3EDFFC })
const positions = []
// const lineGeometry = new Three.BufferGeometry()
const lineGeometry = new Three.BufferGeometry()
for (let i = 0; i < polygon.length; i++) {
var pos = this.getPosition(polygon[i][0] + 90, polygon[i][1], 100)
var pos = getPosition(polygon[i][0] + 90, polygon[i][1], 100)
if (pos.x) {
positions.push(pos.x, pos.y, pos.z)
positions.push(new Three.Vector3(pos.x, pos.y, pos.z))
} else {
console.log(polygon[i])
}
}
lineGeometry.setAttribute('position', positions)
const line = new MeshLine()
//
line.setPoints(positions)
line.setGeometry(lineGeometry)
//
// this.texture = new Three.TextureLoader().load('static/material/stroke.png')
// this.texture.wrapS = this.texture.wrapT = Three.RepeatWrapping
@ -682,7 +583,7 @@ export default {
opacity: 1,
// resolution: new Three.Vector2(window.innerWidth, window.innerHeight),
sizeAttenuation: 1,
lineWidth: 0.3,
lineWidth: 0.002,
transparent: true
// wireframe: true
// map: this.texture
@ -706,8 +607,8 @@ export default {
const positions = []
const linGeometry = new Three.BufferGeometry()
for (let i = 0; i < polygon.length; i++) {
const LL = this.transformToLatLon(polygon[i], continentsJson['hc-transform'].default)
var pos = this.getPosition(LL.x + 90, LL.y, 100)
const LL = transformToLatLon(polygon[i], continentsJson['hc-transform'].default)
var pos = getPosition(LL.x + 90, LL.y, 100)
if (pos.x) {
positions.push(pos.x, pos.y, pos.z)
} else {
@ -723,8 +624,8 @@ export default {
const positions = []
const linGeometry = new Three.BufferGeometry()
for (let i = 0; i < multiPolygon.length; i++) {
const LL = this.transformToLatLon(multiPolygon[i], continentsJson['hc-transform'].default)
var pos = this.getPosition(LL.x + 90, LL.y, 100)
const LL = transformToLatLon(multiPolygon[i], continentsJson['hc-transform'].default)
var pos = getPosition(LL.x + 90, LL.y, 100)
if (pos.x) {
positions.push(pos.x, pos.y, pos.z)
} else {
@ -740,33 +641,6 @@ export default {
})
this.scene.add(map1)
},
// geojson
transformToLatLon(a, b) {
var d = b.jsonmarginX
var f = b.jsonmarginY
var e = b.jsonres
e = void 0 === e ? 1 : e
var n = b.scale
n = void 0 === n ? 1 : n
var t = b.xoffset
var r = b.xpan
var m = b.yoffset
var h = b.ypan
a = {
x: ((a[0] - (void 0 === d ? 0 : d)) / e - (void 0 === r ? 0 : r)) / n + (void 0 === t ? 0 : t),
y: ((a[1] - (void 0 === f ? 0 : f)) / e + (void 0 === h ? 0 : h)) / n + (void 0 === m ? 0 : m)
}
d = b.cosAngle || b.rotation && Math.cos(b.rotation)
f = b.sinAngle || b.rotation && Math.sin(b.rotation)
b = proj4(b.crs, 'WGS84', b.rotation ? {
x: a.x * d + a.y * -f,
y: a.x * f + a.y * d
} : a)
return {
y: b.y,
x: b.x
}
},
init() {
this.initRender()
this.initScene()
@ -788,12 +662,12 @@ export default {
//
// var vector = new Three.Vector3(mouse.x, mouse.y, 0.5).unproject(this.camera)
this.raycaster.setFromCamera(this.mouse, this.camera)
const arr = this.scene.getObjectByName('zs').children.concat(this.scene.getObjectByName('cs').children).concat(this.scene.getObjectByName('dsxs').children).concat(this.scene.getObjectByName('ys').children)
const arr = this.scene.getObjectByName('zs').children.concat(this.scene.getObjectByName('cs').children).concat(this.scene.getObjectByName('ys').children)
var intersects = this.raycaster.intersectObjects(arr, true)
if (intersects.length) {
this.scene.getObjectByName('csText').visible = false
this.scene.getObjectByName('zsText').visible = false
this.scene.getObjectByName('dsxsText').visible = false
// this.scene.getObjectByName('dsxsText').visible = false
this.scene.getObjectByName(this.activeTab + 'Text').visible = true
this.scene.getObjectByName(this.activeTab + 'Text').children.forEach(ele => {
intersects[0].object.position.x - 1 === ele.position.x && intersects[0].object.position.y === ele.position.y && intersects[0].object.position.z === ele.position.z ? ele.visible = true : ele.visible = false
@ -856,7 +730,7 @@ export default {
ctx.fillText('集群数量: ' + _area.clusterNum, borderSize * 30, borderSize * 20 + 300)
ctx.fillText('资源使用率: ' + _area.usagedRate, borderSize * 30, borderSize * 20 + 400)
const markPos = this.getPosition(130.21029 + 90, 23.527138, 100)
const markPos = getPosition(130.21029 + 90, 23.527138, 100)
var texture = new Three.CanvasTexture(ctx.canvas)
texture.needsUpdate = true
var fontMesh = new Three.Sprite(
@ -873,14 +747,14 @@ export default {
//
setMark(_markData) {
this.marking = new Three.Group()
this.textMarking = new Three.Group()
// this.textMarking = new Three.Group()
for (var i = 0; i < _markData.length; i++) {
//
// var mark = new Three.Mesh(new Three.SphereGeometry(2, 2, 2), new Three.MeshBasicMaterial({
// color: '#1bb4b0'
// }))
// //
var markPos = this.getPosition(_markData[i].value[0] + 90, _markData[i].value[1], 100)
var markPos = getPosition(_markData[i].longitude + 90, _markData[i].latitude, 100)
// mark.position.set(markPos.x, markPos.y, markPos.z)
var textureLoader = new Three.TextureLoader()
@ -905,25 +779,25 @@ export default {
mesh.quaternion.setFromUnitVectors(meshNormal, coordVec3)
this.marking.add(mesh)
// eg: 18
var texture = new Three.CanvasTexture(this.getCanvasFont(_markData[i].name + '' + _markData[i].count + '个'))
//
const fontNumber = _markData[i].count.toString().length * 5.8642578125 + _markData[i].name.length * 10 + 10 + 2.4072265625 + 5
texture.needsUpdate = true
var fontMesh = new Three.Sprite(
new Three.SpriteMaterial({
map: texture
})
)
fontMesh.scale.x = fontNumber
fontMesh.scale.y = 10
fontMesh.position.set(markPos.x + 10, markPos.y + 10, markPos.z - 20)
this.textMarking.add(fontMesh)
// // eg: 18
// var texture = new Three.CanvasTexture(this.getCanvasFont(_markData[i].city))
// //
// const fontNumber = _markData[i].city.length * 10 + 2.4072265625 + 5
// texture.needsUpdate = true
// var fontMesh = new Three.Sprite(
// new Three.SpriteMaterial({
// map: texture
// })
// )
// fontMesh.scale.x = fontNumber
// fontMesh.scale.y = 10
// fontMesh.position.set(markPos.x + 10, markPos.y + 10, markPos.z - 20)
// this.textMarking.add(fontMesh)
}
this.marking.name = 'globePoint'
this.textMarking.name = 'globePointText'
// this.textMarking.name = 'globePointText'
this.scene.add(this.marking)
this.scene.add(this.textMarking)
// this.scene.add(this.textMarking)
},
//
getCanvasFont(name) {
@ -972,20 +846,6 @@ export default {
}
return ctx.canvas
},
//
getPosition(_longitude, _latitude, _radius) {
var lg = Three.Math.degToRad(_longitude)
var lt = Three.Math.degToRad(_latitude)
var temp = _radius * Math.cos(lt)
var x = temp * Math.sin(lg)
var y = _radius * Math.sin(lt)
var z = temp * Math.cos(lg)
return {
x: x,
y: y,
z: z
}
},
animate() {
// this.scene.rotation.x = 0.5
// this.scene.rotation.y += 0.005
@ -994,16 +854,16 @@ export default {
//
if (this.scene && this.scene.getObjectByName('globePoint').children.length) {
this.scene.getObjectByName('globePoint').children.forEach((mesh) => {
this.mshs += 0.005
mesh.scale.set(this.mshs, this.mshs, 3 * this.mshs)
if (this.mshs <= 1.5) {
this.mshs += 0.001
mesh.scale.set(this.mshs, this.mshs, 2 * this.mshs)
if (this.mshs <= 1.2) {
// mesh._s=1=0 mesh._s=1.5=1
mesh.material.opacity = (this.mshs - 1) * 2
} else if (this.mshs > 1.5 && this.mshs <= 2) {
mesh.material.opacity = (this.mshs - 0.8) * 2
} else if (this.mshs > 1.2 && this.mshs <= 1.8) {
// mesh._s=1.5=1 mesh._s=2=0
mesh.material.opacity = 1 - (this.mshs - 1.5) * 2
mesh.material.opacity = 1 - (this.mshs - 1.2) * 2
} else {
this.mshs = 1.0
this.mshs = 0.8
}
})
}
@ -1019,71 +879,71 @@ export default {
}
</script>
<style lang="scss" scoped>
.switchBtn {
font-size: 1.5rem;
position: absolute;
bottom: 50px;
right: 29.5vw;
z-index: 100;
color: #fff;
}
.toChina{
right: 32vw;
}
.activeBtn{
color: #3EDFFC
}
.chinaDetail{
position:absolute;
bottom: 80px;
right: 28vw;
z-index: 100;
width: 140px;
.el-button,.el-button + .el-button{
margin: 0;
margin-bottom: 5px;
padding: 5px 15px;
width: 100%;
background-color: #b3afaf33;
<style lang="scss" scoped>
.switchBtn {
font-size: 1.5rem;
position: absolute;
bottom: 50px;
right: 29.5vw;
z-index: 100;
color: #fff;
border-radius: 0;
text-align: left;
border: 0;
line-height: 2rem;
}
.toChina{
right: 32vw;
}
.activeBtn{
color: #3EDFFC
}
.chinaDetail{
position:absolute;
bottom: 80px;
right: 28vw;
z-index: 100;
width: 140px;
.el-button,.el-button + .el-button{
margin: 0;
margin-bottom: 5px;
padding: 5px 15px;
width: 100%;
background-color: #b3afaf33;
color: #fff;
border-radius: 0;
text-align: left;
border: 0;
line-height: 2rem;
.svg-icon{
font-size: 1.4rem;
margin-right: 0.6rem;
}
}
.svg-icon{
font-size: 1.4rem;
font-size: 2rem;
margin-right: 0.6rem;
}
.active{
background-color: #ffffff6b!important;
}
}
.svg-icon{
font-size: 2rem;
margin-right: 0.6rem;
.switchDataBtn{
position: absolute;
bottom: 2vh;
right: 40vw;
.el-button,.el-button + .el-button{
width: 10vw;
margin-bottom: 5px;
padding: 5px 15px;
// width: 100%;
background-color: #24253a;
border-radius: 0;
// text-align: left;
border: 0;
line-height: 3rem;
}
.el-button--default{
color: #efefef;
}
.active{ background-image: linear-gradient(rgba(#3EDFFC,.4),hsla(0,0%,100%,.1),hsla(0,0%,100%,0)); color: #fff;
}
.active{
background-color: #ffffff6b!important;
}
}
.switchDataBtn{
position: absolute;
bottom: 2vh;
right: 40vw;
.el-button,.el-button + .el-button{
width: 10vw;
margin-bottom: 5px;
padding: 5px 15px;
// width: 100%;
background-color: #24253a;
border-radius: 0;
// text-align: left;
border: 0;
line-height: 3rem;
}
.el-button--default{
color: #efefef;
}
.active{ background-image: linear-gradient(rgba(#3EDFFC,.4),hsla(0,0%,100%,.1),hsla(0,0%,100%,0)); color: #fff;
}
}
</style>
</style>

View File

@ -45,13 +45,13 @@ export function createFlyCurve(points, closed) {
// 流光的颜色三个数字分别代表rgb的值不过注意需要除以255
// 比如浅绿色的rgb是(0,255,127)那么这里的Vector3就等于(0,1,127/255)也就是(0,1,0.49803921)
// var color = new THREE.Vector3(0.5999758518718452, 0.7798940272761521, 0.6181903838257632)
var color = new THREE.Color(0x059BFC)
var color = new THREE.Color(0xf3ca45)
var flyLine = initFlyLine(curve, {
speed: 0.6,
color: color,
number: 1, // 同时跑动的流光数量
length: 3, // 流光线条长度
size: 10 // 粗细
length: 4, // 流光线条长度
size: 2 // 粗细
}, 5000)
return flyLine
}

View File

@ -0,0 +1,758 @@
(function() {
'use strict'
var root = this
var has_require = typeof require !== 'undefined'
var THREE = root.THREE || has_require && require('three')
if (!THREE) { throw new Error('MeshLine requires three.js') }
function MeshLine() {
this.positions = []
this.previous = []
this.next = []
this.side = []
this.width = []
this.indices_array = []
this.uvs = []
this.counters = []
this.geometry = new THREE.BufferGeometry()
this.widthCallback = null
// Used to raycast
this.matrixWorld = new THREE.Matrix4()
}
MeshLine.prototype.setMatrixWorld = function(matrixWorld) {
this.matrixWorld = matrixWorld
}
MeshLine.prototype.setGeometry = function(g, c) {
this.widthCallback = c
this.positions = []
this.counters = []
// g.computeBoundingBox();
// g.computeBoundingSphere();
// set the normals
// g.computeVertexNormals();
// if (g instanceof THREE.Geometry) {
// for (var j = 0; j < g.vertices.length; j++) {
// var v = g.vertices[ j ]
// var c = j / g.vertices.length
// this.positions.push(v.x, v.y, v.z)
// this.positions.push(v.x, v.y, v.z)
// this.counters.push(c)
// this.counters.push(c)
// }
// }
if (g instanceof THREE.BufferGeometry) {
// read attribute positions ?
for (var j = 0; j < g.attributes.position.length; j++) {
const v = g.attributes.position[ j ]
const c = j / g.attributes.position.length
this.positions.push(v.x, v.y, v.z)
this.positions.push(v.x, v.y, v.z)
this.counters.push(c)
this.counters.push(c)
}
}
if (g instanceof Float32Array || g instanceof Array) {
for (let j = 0; j < g.length; j += 3) {
const c = j / g.length
this.positions.push(g[ j ], g[ j + 1 ], g[ j + 2 ])
this.positions.push(g[ j ], g[ j + 1 ], g[ j + 2 ])
this.counters.push(c)
this.counters.push(c)
}
}
this.process()
}
MeshLine.prototype.raycast = (function() {
var inverseMatrix = new THREE.Matrix4()
var ray = new THREE.Ray()
var sphere = new THREE.Sphere()
return function raycast(raycaster, intersects) {
var precision = raycaster.linePrecision
var precisionSq = precision * precision
var interRay = new THREE.Vector3()
var geometry = this.geometry
if (geometry.boundingSphere === null) geometry.computeBoundingSphere()
// Checking boundingSphere distance to ray
sphere.copy(geometry.boundingSphere)
sphere.applyMatrix4(this.matrixWorld)
if (raycaster.ray.intersectSphere(sphere, interRay) === false) {
return
}
inverseMatrix.getInverse(this.matrixWorld)
ray.copy(raycaster.ray).applyMatrix4(inverseMatrix)
var vStart = new THREE.Vector3()
var vEnd = new THREE.Vector3()
var interSegment = new THREE.Vector3()
var step = this instanceof THREE.LineSegments ? 2 : 1
if (geometry instanceof THREE.BufferGeometry) {
var index = geometry.index
var attributes = geometry.attributes
if (index !== null) {
var indices = index.array
var positions = attributes.position.array
for (var i = 0, l = indices.length - 1; i < l; i += step) {
var a = indices[ i ]
var b = indices[ i + 1 ]
vStart.fromArray(positions, a * 3)
vEnd.fromArray(positions, b * 3)
var distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment)
if (distSq > precisionSq) continue
interRay.applyMatrix4(this.matrixWorld) // Move back to world space for distance calculation
var distance = raycaster.ray.origin.distanceTo(interRay)
if (distance < raycaster.near || distance > raycaster.far) continue
intersects.push({
distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4(this.matrixWorld),
index: i,
face: null,
faceIndex: null,
object: this
})
}
} else {
const positions = attributes.position.array
for (let i = 0, l = positions.length / 3 - 1; i < l; i += step) {
vStart.fromArray(positions, 3 * i)
vEnd.fromArray(positions, 3 * i + 3)
const distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment)
if (distSq > precisionSq) continue
interRay.applyMatrix4(this.matrixWorld) // Move back to world space for distance calculation
const distance = raycaster.ray.origin.distanceTo(interRay)
if (distance < raycaster.near || distance > raycaster.far) continue
intersects.push({
distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4(this.matrixWorld),
index: i,
face: null,
faceIndex: null,
object: this
})
}
}
} else if (geometry instanceof THREE.Geometry) {
var vertices = geometry.vertices
var nbVertices = vertices.length
for (let i = 0; i < nbVertices - 1; i += step) {
const distSq = ray.distanceSqToSegment(vertices[ i ], vertices[ i + 1 ], interRay, interSegment)
if (distSq > precisionSq) continue
interRay.applyMatrix4(this.matrixWorld) // Move back to world space for distance calculation
const distance = raycaster.ray.origin.distanceTo(interRay)
if (distance < raycaster.near || distance > raycaster.far) continue
intersects.push({
distance: distance,
// What do we want? intersection point on the ray or on the segment??
// point: raycaster.ray.at( distance ),
point: interSegment.clone().applyMatrix4(this.matrixWorld),
index: i,
face: null,
faceIndex: null,
object: this
})
}
}
}
}())
MeshLine.prototype.compareV3 = function(a, b) {
var aa = a * 6
var ab = b * 6
return (this.positions[ aa ] === this.positions[ ab ]) && (this.positions[ aa + 1 ] === this.positions[ ab + 1 ]) && (this.positions[ aa + 2 ] === this.positions[ ab + 2 ])
}
MeshLine.prototype.copyV3 = function(a) {
var aa = a * 6
return [this.positions[ aa ], this.positions[ aa + 1 ], this.positions[ aa + 2 ]]
}
MeshLine.prototype.process = function() {
var l = this.positions.length / 6
this.previous = []
this.next = []
this.side = []
this.width = []
this.indices_array = []
this.uvs = []
for (var j = 0; j < l; j++) {
this.side.push(1)
this.side.push(-1)
}
var w
for (let j = 0; j < l; j++) {
if (this.widthCallback) w = this.widthCallback(j / (l - 1))
else w = 1
this.width.push(w)
this.width.push(w)
}
for (let j = 0; j < l; j++) {
this.uvs.push(j / (l - 1), 0)
this.uvs.push(j / (l - 1), 1)
}
var v
if (this.compareV3(0, l - 1)) {
v = this.copyV3(l - 2)
} else {
v = this.copyV3(0)
}
this.previous.push(v[ 0 ], v[ 1 ], v[ 2 ])
this.previous.push(v[ 0 ], v[ 1 ], v[ 2 ])
for (let j = 0; j < l - 1; j++) {
v = this.copyV3(j)
this.previous.push(v[ 0 ], v[ 1 ], v[ 2 ])
this.previous.push(v[ 0 ], v[ 1 ], v[ 2 ])
}
for (let j = 1; j < l; j++) {
v = this.copyV3(j)
this.next.push(v[ 0 ], v[ 1 ], v[ 2 ])
this.next.push(v[ 0 ], v[ 1 ], v[ 2 ])
}
if (this.compareV3(l - 1, 0)) {
v = this.copyV3(1)
} else {
v = this.copyV3(l - 1)
}
this.next.push(v[ 0 ], v[ 1 ], v[ 2 ])
this.next.push(v[ 0 ], v[ 1 ], v[ 2 ])
for (let j = 0; j < l - 1; j++) {
var n = j * 2
this.indices_array.push(n, n + 1, n + 2)
this.indices_array.push(n + 2, n + 1, n + 3)
}
if (!this.attributes) {
this.attributes = {
position: new THREE.BufferAttribute(new Float32Array(this.positions), 3),
previous: new THREE.BufferAttribute(new Float32Array(this.previous), 3),
next: new THREE.BufferAttribute(new Float32Array(this.next), 3),
side: new THREE.BufferAttribute(new Float32Array(this.side), 1),
width: new THREE.BufferAttribute(new Float32Array(this.width), 1),
uv: new THREE.BufferAttribute(new Float32Array(this.uvs), 2),
index: new THREE.BufferAttribute(new Uint16Array(this.indices_array), 1),
counters: new THREE.BufferAttribute(new Float32Array(this.counters), 1)
}
} else {
this.attributes.position.copyArray(new Float32Array(this.positions))
this.attributes.position.needsUpdate = true
this.attributes.previous.copyArray(new Float32Array(this.previous))
this.attributes.previous.needsUpdate = true
this.attributes.next.copyArray(new Float32Array(this.next))
this.attributes.next.needsUpdate = true
this.attributes.side.copyArray(new Float32Array(this.side))
this.attributes.side.needsUpdate = true
this.attributes.width.copyArray(new Float32Array(this.width))
this.attributes.width.needsUpdate = true
this.attributes.uv.copyArray(new Float32Array(this.uvs))
this.attributes.uv.needsUpdate = true
this.attributes.index.copyArray(new Uint16Array(this.indices_array))
this.attributes.index.needsUpdate = true
}
this.geometry.setAttribute('position', this.attributes.position)
this.geometry.setAttribute('previous', this.attributes.previous)
this.geometry.setAttribute('next', this.attributes.next)
this.geometry.setAttribute('side', this.attributes.side)
this.geometry.setAttribute('width', this.attributes.width)
this.geometry.setAttribute('uv', this.attributes.uv)
this.geometry.setAttribute('counters', this.attributes.counters)
// this.geometry.addAttribute('position', this.attributes.position)
// this.geometry.addAttribute('previous', this.attributes.previous)
// this.geometry.addAttribute('next', this.attributes.next)
// this.geometry.addAttribute('side', this.attributes.side)
// this.geometry.addAttribute('width', this.attributes.width)
// this.geometry.addAttribute('uv', this.attributes.uv)
// this.geometry.addAttribute('counters', this.attributes.counters)
this.geometry.setIndex(this.attributes.index)
}
function memcpy(src, srcOffset, dst, dstOffset, length) {
var i
src = src.subarray || src.slice ? src : src.buffer
dst = dst.subarray || dst.slice ? dst : dst.buffer
src = srcOffset ? src.subarray
? src.subarray(srcOffset, length && srcOffset + length)
: src.slice(srcOffset, length && srcOffset + length) : src
if (dst.set) {
dst.set(src, dstOffset)
} else {
for (i = 0; i < src.length; i++) {
dst[i + dstOffset] = src[i]
}
}
return dst
}
/**
* Fast method to advance the line by one position. The oldest position is removed.
* @param position
*/
MeshLine.prototype.advance = function(position) {
var positions = this.attributes.position.array
var previous = this.attributes.previous.array
var next = this.attributes.next.array
var l = positions.length
// PREVIOUS
memcpy(positions, 0, previous, 0, l)
// POSITIONS
memcpy(positions, 6, positions, 0, l - 6)
positions[l - 6] = position.x
positions[l - 5] = position.y
positions[l - 4] = position.z
positions[l - 3] = position.x
positions[l - 2] = position.y
positions[l - 1] = position.z
// NEXT
memcpy(positions, 6, next, 0, l - 6)
next[l - 6] = position.x
next[l - 5] = position.y
next[l - 4] = position.z
next[l - 3] = position.x
next[l - 2] = position.y
next[l - 1] = position.z
this.attributes.position.needsUpdate = true
this.attributes.previous.needsUpdate = true
this.attributes.next.needsUpdate = true
}
THREE.ShaderChunk[ 'meshline_vert' ] = [
'',
THREE.ShaderChunk.logdepthbuf_pars_vertex,
THREE.ShaderChunk.fog_pars_vertex,
'',
'attribute vec3 previous;',
'attribute vec3 next;',
'attribute float side;',
'attribute float width;',
'attribute float counters;',
'',
'uniform vec2 resolution;',
'uniform float lineWidth;',
'uniform vec3 color;',
'uniform float opacity;',
'uniform float near;',
'uniform float far;',
'uniform float sizeAttenuation;',
'uniform vec2 offset;',
'',
'varying vec2 vUV;',
'varying vec4 vColor;',
'varying float vCounters;',
'',
'vec2 fix( vec4 i, float aspect ) {',
'',
' vec2 res = i.xy / i.w;',
' res.x *= aspect;',
' vCounters = counters;',
' return res;',
'',
'}',
'',
'void main() {',
'',
' float aspect = resolution.x / resolution.y;',
' float pixelWidthRatio = 1. / (resolution.x * projectionMatrix[0][0]);',
'',
' vColor = vec4( color, opacity );',
' vUV = uv + offset;',
'',
' mat4 m = projectionMatrix * modelViewMatrix;',
' vec4 finalPosition = m * vec4( position, 1.0 );',
' vec4 prevPos = m * vec4( previous, 1.0 );',
' vec4 nextPos = m * vec4( next, 1.0 );',
'',
' vec2 currentP = fix( finalPosition, aspect );',
' vec2 prevP = fix( prevPos, aspect );',
' vec2 nextP = fix( nextPos, aspect );',
'',
' float pixelWidth = finalPosition.w * pixelWidthRatio;',
' float w = 1.8 * pixelWidth * lineWidth * width;',
'',
' if( sizeAttenuation == 1. ) {',
' w = 1.8 * lineWidth * width;',
' }',
'',
' vec2 dir;',
' if( nextP == currentP ) dir = normalize( currentP - prevP );',
' else if( prevP == currentP ) dir = normalize( nextP - currentP );',
' else {',
' vec2 dir1 = normalize( currentP - prevP );',
' vec2 dir2 = normalize( nextP - currentP );',
' dir = normalize( dir1 + dir2 );',
'',
' vec2 perp = vec2( -dir1.y, dir1.x );',
' vec2 miter = vec2( -dir.y, dir.x );',
' //w = clamp( w / dot( miter, perp ), 0., 4. * lineWidth * width );',
'',
' }',
'',
' //vec2 normal = ( cross( vec3( dir, 0. ), vec3( 0., 0., 1. ) ) ).xy;',
' vec2 normal = vec2( -dir.y, dir.x );',
' normal.x /= aspect;',
' normal *= .5 * w;',
'',
' vec4 offset = vec4( normal * side, 0.0, 1.0 );',
' finalPosition.xy += offset.xy;',
'',
' gl_Position = finalPosition;',
'',
THREE.ShaderChunk.logdepthbuf_vertex,
THREE.ShaderChunk.fog_vertex && ' vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );',
THREE.ShaderChunk.fog_vertex,
'}'
].join('\r\n')
THREE.ShaderChunk[ 'meshline_frag' ] = [
'',
THREE.ShaderChunk.fog_pars_fragment,
THREE.ShaderChunk.logdepthbuf_pars_fragment,
'',
'uniform sampler2D map;',
'uniform sampler2D alphaMap;',
'uniform float useMap;',
'uniform float useAlphaMap;',
'uniform float useDash;',
'uniform float dashArray;',
'uniform float dashOffset;',
'uniform float dashRatio;',
'uniform float visibility;',
'uniform float alphaTest;',
'uniform vec2 repeat;',
'',
'varying vec2 vUV;',
'varying vec4 vColor;',
'varying float vCounters;',
'',
'void main() {',
'',
THREE.ShaderChunk.logdepthbuf_fragment,
'',
' vec4 c = vColor;',
' if( useMap == 1. ) c *= texture2D( map, vUV * repeat );',
' if( useAlphaMap == 1. ) c.a *= texture2D( alphaMap, vUV * repeat ).a;',
' if( c.a < alphaTest ) discard;',
' if( useDash == 1. ){',
' c.a *= ceil(mod(vCounters + dashOffset, dashArray) - (dashArray * dashRatio));',
' }',
' gl_FragColor = c;',
' gl_FragColor.a *= step(vCounters, visibility);',
'',
THREE.ShaderChunk.fog_fragment,
'}'
].join('\r\n')
function MeshLineMaterial(parameters) {
THREE.ShaderMaterial.call(this, {
uniforms: Object.assign({},
THREE.UniformsLib.fog,
{
lineWidth: { value: 1 },
map: { value: null },
useMap: { value: 0 },
alphaMap: { value: null },
useAlphaMap: { value: 0 },
color: { value: new THREE.Color(0xffffff) },
opacity: { value: 1 },
resolution: { value: new THREE.Vector2(1, 1) },
sizeAttenuation: { value: 1 },
near: { value: 1 },
far: { value: 1 },
dashArray: { value: 0 },
dashOffset: { value: 0 },
dashRatio: { value: 0.5 },
useDash: { value: 0 },
visibility: { value: 1 },
alphaTest: { value: 0 },
repeat: { value: new THREE.Vector2(1, 1) },
offset: { value: new THREE.Vector2(1, 1) }
}
),
vertexShader: THREE.ShaderChunk.meshline_vert,
fragmentShader: THREE.ShaderChunk.meshline_frag
})
this.type = 'MeshLineMaterial'
Object.defineProperties(this, {
lineWidth: {
enumerable: true,
get: function() {
return this.uniforms.lineWidth.value
},
set: function(value) {
this.uniforms.lineWidth.value = value
}
},
map: {
enumerable: true,
get: function() {
return this.uniforms.map.value
},
set: function(value) {
this.uniforms.map.value = value
}
},
useMap: {
enumerable: true,
get: function() {
return this.uniforms.useMap.value
},
set: function(value) {
this.uniforms.useMap.value = value
}
},
alphaMap: {
enumerable: true,
get: function() {
return this.uniforms.alphaMap.value
},
set: function(value) {
this.uniforms.alphaMap.value = value
}
},
useAlphaMap: {
enumerable: true,
get: function() {
return this.uniforms.useAlphaMap.value
},
set: function(value) {
this.uniforms.useAlphaMap.value = value
}
},
color: {
enumerable: true,
get: function() {
return this.uniforms.color.value
},
set: function(value) {
this.uniforms.color.value = value
}
},
opacity: {
enumerable: true,
get: function() {
return this.uniforms.opacity.value
},
set: function(value) {
this.uniforms.opacity.value = value
}
},
resolution: {
enumerable: true,
get: function() {
return this.uniforms.resolution.value
},
set: function(value) {
this.uniforms.resolution.value.copy(value)
}
},
sizeAttenuation: {
enumerable: true,
get: function() {
return this.uniforms.sizeAttenuation.value
},
set: function(value) {
this.uniforms.sizeAttenuation.value = value
}
},
near: {
enumerable: true,
get: function() {
return this.uniforms.near.value
},
set: function(value) {
this.uniforms.near.value = value
}
},
far: {
enumerable: true,
get: function() {
return this.uniforms.far.value
},
set: function(value) {
this.uniforms.far.value = value
}
},
dashArray: {
enumerable: true,
get: function() {
return this.uniforms.dashArray.value
},
set: function(value) {
this.uniforms.dashArray.value = value
this.useDash = (value !== 0) ? 1 : 0
}
},
dashOffset: {
enumerable: true,
get: function() {
return this.uniforms.dashOffset.value
},
set: function(value) {
this.uniforms.dashOffset.value = value
}
},
dashRatio: {
enumerable: true,
get: function() {
return this.uniforms.dashRatio.value
},
set: function(value) {
this.uniforms.dashRatio.value = value
}
},
useDash: {
enumerable: true,
get: function() {
return this.uniforms.useDash.value
},
set: function(value) {
this.uniforms.useDash.value = value
}
},
visibility: {
enumerable: true,
get: function() {
return this.uniforms.visibility.value
},
set: function(value) {
this.uniforms.visibility.value = value
}
},
alphaTest: {
enumerable: true,
get: function() {
return this.uniforms.alphaTest.value
},
set: function(value) {
this.uniforms.alphaTest.value = value
}
},
repeat: {
enumerable: true,
get: function() {
return this.uniforms.repeat.value
},
set: function(value) {
this.uniforms.repeat.value.copy(value)
}
}
})
this.setValues(parameters)
}
MeshLineMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype)
MeshLineMaterial.prototype.constructor = MeshLineMaterial
MeshLineMaterial.prototype.isMeshLineMaterial = true
MeshLineMaterial.prototype.copy = function(source) {
THREE.ShaderMaterial.prototype.copy.call(this, source)
this.lineWidth = source.lineWidth
this.map = source.map
this.useMap = source.useMap
this.alphaMap = source.alphaMap
this.useAlphaMap = source.useAlphaMap
this.color.copy(source.color)
this.opacity = source.opacity
this.resolution.copy(source.resolution)
this.sizeAttenuation = source.sizeAttenuation
this.near = source.near
this.far = source.far
this.dashArray.copy(source.dashArray)
this.dashOffset.copy(source.dashOffset)
this.dashRatio.copy(source.dashRatio)
this.useDash = source.useDash
this.visibility = source.visibility
this.alphaTest = source.alphaTest
this.repeat.copy(source.repeat)
return this
}
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = { MeshLine: MeshLine, MeshLineMaterial: MeshLineMaterial }
}
exports.MeshLine = MeshLine
exports.MeshLineMaterial = MeshLineMaterial
} else {
root.MeshLine = MeshLine
root.MeshLineMaterial = MeshLineMaterial
}
}).call(this)