我试图创建一个基于D3 & Three.js对象的Vue 3组件,我在网上找到了Mike Bostock编写的这个对象。
这是我想使用的对象:https://bl.ocks.org/mbostock/2b85250396c17a79155302f91ec21224
它是以HTML代码的形式提供的,当复制到html文件中时可以立即工作。
我已经下载了d3、three和其他依赖项,并使用loadScript加载了其他脚本。我使用Vite作为工具。当我在页面上加载组件时,什么也没有出现。控制台中也没有错误。
这是我到目前为止所拥有的Vue代码。这是一个可靠的方法吗?有没有更好的方法来集成这个对象?我对Vue还是一个新手,任何帮助都是非常感谢的。
- 谢谢-谢谢
<template>
<div id="globe" style="height:500px; width:700px"></div>
</template>
<script>
import * as THREE from 'three';
import * as d3 from 'd3'
import { loadScript } from "vue-plugin-load-script";
import { onMounted } from 'vue';
loadScript("https://unpkg.com/three@0.84");
loadScript("https://unpkg.com/topojson-client@3");
loadScript("https://unpkg.com/d3-array@1");
loadScript("https://unpkg.com/d3-collection@1");
loadScript("https://unpkg.com/d3-dispatch@1");
loadScript("https://unpkg.com/d3-request@1");
loadScript("https://unpkg.com/d3-timer@1");
var globe = document.getElementById('globe');
onMounted(() => {
console.log('mounted!')
var radius = 228,
mesh,
graticule,
scene = new THREE.Scene,
camera = new THREE.PerspectiveCamera(70, globe.clientWidth/globe.clientHeight, 1, 1000),
renderer = new THREE.WebGLRenderer({alpha: true});
camera.position.z = 400;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(globe.clientWidth, globe.clientHeight);
globe.appendChild(renderer.domElement);
d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function(error, topology) {
if (error) throw error;
scene.add(graticule = wireframe(graticule10(), new THREE.LineBasicMaterial({color: 0xaaaaaa})));
scene.add(mesh = wireframe(topojson.mesh(topology, topology.objects.land), new THREE.LineBasicMaterial({color: 0xff0000})));
d3.timer(function(t) {
graticule.rotation.x = mesh.rotation.x = Math.sin(t / 11000) * Math.PI / 3 - Math.PI / 2;
graticule.rotation.z = mesh.rotation.z = t / 10000;
renderer.render(scene, camera);
});
});
// Converts a point [longitude, latitude] in degrees to a THREE.Vector3.
function vertex(point) {
var lambda = point[0] * Math.PI / 180,
phi = point[1] * Math.PI / 180,
cosPhi = Math.cos(phi);
return new THREE.Vector3(
radius * cosPhi * Math.cos(lambda),
radius * cosPhi * Math.sin(lambda),
radius * Math.sin(phi)
);
}
// Converts a GeoJSON MultiLineString in spherical coordinates to a THREE.LineSegments.
function wireframe(multilinestring, material) {
var geometry = new THREE.Geometry;
multilinestring.coordinates.forEach(function(line) {
d3.pairs(line.map(vertex), function(a, b) {
geometry.vertices.push(a, b);
});
});
return new THREE.LineSegments(geometry, material);
}
// See https://github.com/d3/d3-geo/issues/95
function graticule10() {
var epsilon = 1e-6,
x1 = 180, x0 = -x1, y1 = 80, y0 = -y1, dx = 10, dy = 10,
X1 = 180, X0 = -X1, Y1 = 90, Y0 = -Y1, DX = 90, DY = 360,
x = graticuleX(y0, y1, 2.5), y = graticuleY(x0, x1, 2.5),
X = graticuleX(Y0, Y1, 2.5), Y = graticuleY(X0, X1, 2.5);
function graticuleX(y0, y1, dy) {
var y = d3.range(y0, y1 - epsilon, dy).concat(y1);
return function(x) { return y.map(function(y) { return [x, y]; }); };
}
function graticuleY(x0, x1, dx) {
var x = d3.range(x0, x1 - epsilon, dx).concat(x1);
return function(y) { return x.map(function(x) { return [x, y]; }); };
}
return {
type: "MultiLineString",
coordinates: d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X)
.concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y))
.concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return Math.abs(x % DX) > epsilon; }).map(x))
.concat(d3.range(Math.ceil(y0 / dy) * dy, y1 + epsilon, dy).filter(function(y) { return Math.abs(y % DY) > epsilon; }).map(y))
};
}
})
</script>
1条答案
按热度按时间qco9c6ql1#
我不认为您需要使用loadscript来加载d3 & THREEjs依赖项,因为您正在导入的npm包已经包含了这些依赖项。
您还需要安装topojson-client并将其导入。
下面的代码对我有用。screenshot
关于我所做更改的一些说明:
1.使用合成API时,
<script>
标记需要设置属性。<script setup>
1.我使用模板引用来获得div元素,但是你原来的方法也应该可以。
我的软件包. json