https:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Three.js入门</title>
<style>
#tooltip {
position: fixed;
z-index: 999;
background: white;
padding: 10px;
border-radius: 2px;
visibility: hidden;
user-select: none;
}
#canvas{
position: relative;
z-index: 1;
}
</style>
</head>
<body>
<script src="./script.js" type="module"></script>
<div id="tooltip"></div>
</body>
</html>
import { geoMercator } from "d3-geo";
import floor from "./images/floor_wood.jpeg";
import uv from "./images/uv.png";
import grass_top from "./images/grass_top.png";
import grass_side from "./images/grass_side.png";
import grass_bottom from "./images/grass_bottom.png";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
precision: 'highp',
premultipliedAlpha: false,
preserveDrawingBuffer: true,
maxLights: 3,
stencil: false
});
renderer.pixelRatio = window.devicePixelRatio;
renderer.setSize(window.innerWidth, window.innerHeight);
class chinaMap {
constructor() {
this.init()
}
init() {
this.scene = new THREE.Scene()
this.setCamera()
this.setRenderer()
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const cube = new THREE.Mesh(geometry, material)
this.render()
this.loadMapData()
this.addHelper()
this.setController()
this.setRaycaster()
this.animate()
}
setController() {
this.controller = new OrbitControls(
this.camera,
document.getElementById('canvas')
)
}
addHelper() {
const helper = new THREE.CameraHelper(this.camera)
this.scene.add(helper)
}
loadMapData() {
const loader = new THREE.FileLoader()
console.log();
this.generateGeometry(require('./china.json'))
}
render() {
this.renderer.render(this.scene, this.camera)
}
showTip() {
if (this.lastPick) {
const properties = this.lastPick.object.parent.properties
this.tooltip.textContent = properties.name
this.tooltip.style.visibility = 'visible'
} else {
this.tooltip.style.visibility = 'hidden'
}
}
setRaycaster() {
this.raycaster = new THREE.Raycaster()
this.mouse = new THREE.Vector2()
this.tooltip = document.getElementById('tooltip')
const onMouseMove = (event) => {
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
this.tooltip.style.left = event.clientX + 2 + 'px'
this.tooltip.style.top = event.clientY + 2 + 'px'
}
window.addEventListener('mousemove', onMouseMove, false)
}
animate() {
requestAnimationFrame(this.animate.bind(this))
this.raycaster.setFromCamera(this.mouse, this.camera)
const intersects = this.raycaster.intersectObjects(
this.scene.children,
true
)
if (this.lastPick) {
this.lastPick.object.material[0].color.set('#2defff')
this.lastPick.object.material[1].color.set('#3480C4')
}
this.lastPick = null
this.lastPick = intersects.find(
(item) => item.object.material && item.object.material.length === 2
)
if (this.lastPick) {
this.lastPick.object.material[0].color.set(0xff0000)
this.lastPick.object.material[1].color.set(0xff0000)
}
this.showTip()
this.render()
}
setCamera() {
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
this.camera.position.z = 100
}
setRenderer() {
this.renderer = new THREE.WebGLRenderer()
this.renderer.setSize(window.innerWidth, window.innerHeight)
this.renderer.domElement.setAttribute('id','canvas')
document.body.appendChild(this.renderer.domElement)
}
setLight() {
this.ambientLight = new THREE.AmbientLight(0xffffff)
this.scene.add(ambientLight)
}
generateGeometry(jsondata) {
console.log(jsondata);
this.map = new THREE.Object3D()
const projection = geoMercator()
.center([104.0, 37.5])
.scale(80)
.translate([0, 0])
jsondata.features.forEach((elem) => {
const province = new THREE.Object3D()
province.properties = elem.properties
this.map.add(province)
const coordinates = elem.geometry.coordinates
console.log(coordinates);
coordinates.forEach((multiPolygon) => {
multiPolygon.forEach((polygon) => {
const shape = new THREE.Shape()
const lineMaterial = new THREE.LineBasicMaterial({
color: 'white',
})
const lineGeometry = new THREE.BufferGeometry()
const points = [];
for (let i = 0; i < polygon.length; i++) {
const [x, y] = projection(polygon[i])
if (i === 0) {
shape.moveTo(x, -y)
}
shape.lineTo(x, -y)
points.push(new THREE.Vector3(x, -y, 4.01))
}
lineGeometry.setFromPoints(points);
const extrudeSettings = {
depth: 10,
bevelEnabled: false,
}
const geometry = new THREE.ExtrudeGeometry(
shape,
extrudeSettings
)
const material = new THREE.MeshBasicMaterial({
color: '#2defff',
transparent: true,
opacity: 0.6,
})
const material1 = new THREE.MeshBasicMaterial({
color: '#3480C4',
transparent: true,
opacity: 0.5,
})
const mesh = new THREE.Mesh(geometry, [material, material1])
const line = new THREE.Line(lineGeometry, lineMaterial)
province.add(mesh)
province.add(line)
})
})
})
this.scene.add(this.map)
this.render()
}
}
let a = new chinaMap()
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
2020-11-07 vue cli3及4使用官方方法配置scss全局变量报错
2020-11-07 Vue中Class与Style几种绑定用法