【问题标题】:d3.js | projection.rotate() return value [NaN, 0, 0]d3.js | projection.rotate() 返回值 [NaN, 0, 0]
【发布时间】:2021-08-09 08:35:59
【问题描述】:

我想使用projection.rotate() 旋转地球画布,但它返回值[NaN, 0, 0]

<template lang="html">
  <div class="map" style="width:100vw;height:100vh">
    <canvas id="globe"></canvas>
  </div>
</template>

<script lang="js">
import * as d3 from "d3";
import * as topojson from "topojson-client";

export default {
  name: 'vue',
  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,
      degPerMs: this.degPerSec / 1000,
      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,
    }
  },
  mounted() {
    this.canvas = document.getElementById('globe');
    this.context = this.canvas.getContext('2d');
    this.path = d3.geoPath(this.projection).context(this.context);
    this.loadData((world, cList)=> {
      this.land = topojson.feature(world, world.objects.land);
      this.countries = topojson.feature(world, world.objects.countries);
      this.countryList = cList;
      window.addEventListener('resize', this.scale);
      this.scale();
      this.autorotate = d3.timer(this.rotate);
    });
  },
  methods: {
    loadData(cb) {
      d3.json('https://unpkg.com/world-atlas@1/world/110m.json').then(function(world) {
        d3.tsv('https://gist.githubusercontent.com/mbostock/4090846/raw/07e73f3c2d21558489604a0bc434b3a5cf41a867/world-country-names.tsv').then( function(countries) {
          cb(world, countries)
        })
      })
    },
    rotate(elapsed) {
      this.now = d3.now();
      this.diff = this.now - this.lastTime;
      if (elapsed < 300) { //this.diff !== elapsed
        let rotation = this.projection.rotate();
        console.log(rotation);
        rotation[0] += this.diff * this.degPerMs;
        this.projection.rotate(rotation);
        this.render();
      }
      this.lastTime = this.now;
    },
    render() {
      this.context.clearRect(0, 0, this.width, this.height);
      this.fill(this.water, this.colorWater)
      this.stroke(this.graticule, this.colorGraticule)
      this.fill(this.land, this.colorLand)
      if (this.currentCountry) {
        this.fill(this.currentCountry, this.colorCountry)
      }
    },
    fill(obj, color) {
      this.context.beginPath()
      this.path(obj)
      this.context.fillStyle = color
      this.context.fill()
    },
    stroke(obj, color) {
      this.context.beginPath()
      this.path(obj)
      this.context.strokeStyle = color
      this.context.stroke()
    },
    scale() {
      this.width = document.querySelector(".map").clientWidth;
      this.height = document.querySelector(".map").clientHeight;
      this.canvas.setAttribute('width', this.width);
      this.canvas.setAttribute('height', this.height);
      this.projection
        .scale((this.scaleFactor * Math.min(this.width, this.height)) / 2)
        .translate([this.width / 2, this.height / 2])
      this.render();
    }
  },
}
</script>

你可以在这里查看我的问题:https://codesandbox.io/s/globe-issus-q2s1s

示例旋转演示:https://codepen.io/Share2U/pen/dyWQoGv

感谢您的帮助。

【问题讨论】:

    标签: vue.js d3.js canvas


    【解决方案1】:

    问题出在下面一行:

    degPerMs: this.degPerSec / 1000,
    

    this.degPerSec 不可用,因为您无法访问 data 中的其他 data 属性。因此rotation[0] += this.diff * this.degPerMs; 正在返回NaN

    要解决此问题,您可以在导出模块之前设置一个变量。

    例如:

    <script lang="js">
    import * as d3 from "d3";
    import * as topojson from "topojson-client";
    
    const DEG_PER_SEC = 6;
    
    export default {
      name: 'vue',
      data() {
        return {
          ...
          degPerMs: DEG_PER_SEC / 1000,
          ...
        }
      }
    }
    </script>
    

    【讨论】:

    • @TaSvet 不客气!如果您愿意,可以将我的答案标记为已接受的答案。
    猜你喜欢
    • 2015-06-16
    • 1970-01-01
    • 2020-01-17
    • 2015-11-27
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多