使用D3.js projection.rotate()实现地球画布旋转时返回[NaN, 0, 0]的技术问题求助
我仔细看了你的Vue项目代码,找到问题的根源了:组件data初始化时degPerMs的计算有误,导致旋转角度变成了NaN,进而让projection.rotate()返回[NaN, 0, 0],旋转功能失效。
问题原因
在你的data选项里,你尝试用this.degPerSec / 1000来初始化degPerMs,但此时Vue组件实例还未完全创建,this还无法正确访问到degPerSec属性,最终degPerMs的值变成了NaN。当你在rotate方法里执行rotation[0] += this.diff * this.degPerMs时,rotation[0]就会被赋值为NaN,传递给projection.rotate()后自然无法正常工作。
另外还有一个潜在问题:你直接把this.rotate传给d3.timer,如果不绑定this,回调里的this可能不会指向组件实例,导致无法访问到projection等属性。
解决步骤
下面是具体的修改方案:
移除data中
degPerMs的错误初始化
先从data里删掉degPerMs: this.degPerSec / 1000这一行,避免初始化时的错误。在rotate方法内计算degPerMs
每次调用rotate时再计算degPerMs,确保能获取到组件实例中正确的degPerSec值。确保rotate方法的this指向组件实例
在mounted里给d3.timer的回调绑定组件实例的this,或者用箭头函数包裹。
修改后的关键代码
1. 更新data选项
data() { return { angles: { x: -20, y: 40, z: 0 }, canvas: null, context: null, countries: null, countryList: null, autorotate: null, lastTime: d3.now(), now: null, diff: null, roation: null, scaleFactor: 0.6, degPerSec: 6, width: null, height: null, water: { type: 'Sphere' }, colorWater: '#0099cf', colorLand: '#77fc2f', colorGraticule: '#0099cf', colorCountry: '#77fc2f', land: null, currentCountry: null, graticule: d3.geoGraticule10(), projection: d3.geoOrthographic().precision(0.1), path: null, } },
2. 更新mounted钩子中的timer绑定
mounted() { // ... 其他代码保持不变 // 用箭头函数确保this指向组件实例 this.autorotate = d3.timer(() => this.rotate()); },
3. 更新rotate方法
rotate(elapsed) { this.now = d3.now(); this.diff = this.now - this.lastTime; // 在这里计算degPerMs,确保值正确 const degPerMs = this.degPerSec / 1000; if (elapsed < 300) { let rotation = this.projection.rotate(); rotation[0] += this.diff * degPerMs; this.projection.rotate(rotation); this.render(); } this.lastTime = this.now; },
验证效果
修改完成后,你再调用projection.rotate()就会返回正常的数值数组,地球画布也能按照你设置的速度自动旋转了。
内容的提问来源于stack exchange,提问作者TaSvet

