将 Bl.ocks.org 图实现到 Vue.js 组件中
Implementing a Bl.ocks.org graph into a Vue.js component
我是 D3 初学者,我想在我的 Vue.js 组件中使用 this d3 元素。这里的问题是我需要的周期性轮换不起作用。它开始在全局定义的元素投影上循环 null 错误。似乎第一次有效,但在第二次中,对象不再定义。
代码如下:
<template>
<div>
<svg></svg>
</div>
</template>
<script>
import * as d3 from "d3";
import { feature } from "topojson-client";
import { json } from "d3-fetch";
export default {
name: "WorldCases",
data: function() {
return {
svg: null,
markerGroup: null,
projection: null,
initialScale: null,
path: null,
center: null,
config: null,
locations: [
{ latitude: 22, longitude: 88 },
{ latitude: 12.61315, longitude: 38.37723 },
{ latitude: -30, longitude: -58 },
{ latitude: -14.270972, longitude: -170.132217 },
{ latitude: 28.033886, longitude: 1.659626 },
{ latitude: 40.463667, longitude: -3.74922 },
{ latitude: 35.907757, longitude: 127.766922 },
{ latitude: 23.634501, longitude: -102.552784 },
],
};
},
mounted() {
this.graph();
},
methods: {
graph() {
const width = 960;
const height = 500;
this.config = {
speed: 0.005,
verticalTilt: -30,
horizontalTilt: 0,
};
this.svg = d3
.select("svg")
.attr("width", width)
.attr("height", height);
this.markerGroup = this.svg.append("g");
this.projection = d3.geoOrthographic();
console.log(this.projection);
this.initialScale = this.projection.scale();
this.path = d3.geoPath().projection(this.projection);
this.center = [width / 2, height / 2];
this.drawGlobe();
this.drawGraticule();
d3.timer(function(elapsed) {
this.projection.rotate([
this.config.speed * elapsed - 120,
this.config.verticalTilt,
this.config.horizontalTilt,
]);
this.svg.selectAll("path").attr("d", this.path);
this.drawMarkers();
});
},
drawGlobe() {
Promise.all([json("./world-110m.json")]).then(([worldData, error]) => {
// Do your stuff. Content of both files is now available in stations and svg
this.svg
.selectAll(".segment")
.data(feature(worldData, worldData.objects.countries).features)
.enter()
.append("path")
.attr("class", "segment")
.attr("d", this.path)
.style("stroke", "#888")
.style("stroke-width", "1px")
.style("fill", (d, i) => "#e5e5e5")
.style("opacity", ".6");
this.drawMarkers();
});
},
drawMarkers() {
const markers = this.markerGroup.selectAll("circle").data(this.locations);
markers
.enter()
.append("circle")
.merge(markers)
.attr("cx", (d) => this.projection([d.longitude, d.latitude])[0])
.attr("cy", (d) => this.projection([d.longitude, d.latitude])[1])
.attr("fill", (d) => {
const coordinate = [d.longitude, d.latitude];
var gdistance = d3.geoDistance(coordinate, this.projection.invert(this.center));
return gdistance > 1.57 ? "none" : "steelblue";
})
.attr("r", 7);
this.markerGroup.each(function() {
this.parentNode.appendChild(this);
});
},
drawGraticule() {
const graticule = d3.geoGraticule().step([10, 10]);
this.svg
.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", this.path)
.style("fill", "#fff")
.style("stroke", "#ccc");
},
},
};
</script>
<style></style>
错误如下图所示:
我该如何解决?在此配置中它不起作用。
谢谢
我解决了我的问题,记得在 Javascript 中,当我们在其他函数中工作时,有时“this”元素并不总是我们所期望的。
所以我需要做的是将“this”对象保存在一个变量中并使用该变量来执行我需要的操作:
var x = this;
d3.timer(function(elapsed) {
x.projection.rotate([
x.config.speed * elapsed - 120,
x.config.verticalTilt,
x.config.horizontalTilt,
]);
x.svg.selectAll("path").attr("d", this.path);
x.drawMarkers();
});
我是 D3 初学者,我想在我的 Vue.js 组件中使用 this d3 元素。这里的问题是我需要的周期性轮换不起作用。它开始在全局定义的元素投影上循环 null 错误。似乎第一次有效,但在第二次中,对象不再定义。
代码如下:
<template>
<div>
<svg></svg>
</div>
</template>
<script>
import * as d3 from "d3";
import { feature } from "topojson-client";
import { json } from "d3-fetch";
export default {
name: "WorldCases",
data: function() {
return {
svg: null,
markerGroup: null,
projection: null,
initialScale: null,
path: null,
center: null,
config: null,
locations: [
{ latitude: 22, longitude: 88 },
{ latitude: 12.61315, longitude: 38.37723 },
{ latitude: -30, longitude: -58 },
{ latitude: -14.270972, longitude: -170.132217 },
{ latitude: 28.033886, longitude: 1.659626 },
{ latitude: 40.463667, longitude: -3.74922 },
{ latitude: 35.907757, longitude: 127.766922 },
{ latitude: 23.634501, longitude: -102.552784 },
],
};
},
mounted() {
this.graph();
},
methods: {
graph() {
const width = 960;
const height = 500;
this.config = {
speed: 0.005,
verticalTilt: -30,
horizontalTilt: 0,
};
this.svg = d3
.select("svg")
.attr("width", width)
.attr("height", height);
this.markerGroup = this.svg.append("g");
this.projection = d3.geoOrthographic();
console.log(this.projection);
this.initialScale = this.projection.scale();
this.path = d3.geoPath().projection(this.projection);
this.center = [width / 2, height / 2];
this.drawGlobe();
this.drawGraticule();
d3.timer(function(elapsed) {
this.projection.rotate([
this.config.speed * elapsed - 120,
this.config.verticalTilt,
this.config.horizontalTilt,
]);
this.svg.selectAll("path").attr("d", this.path);
this.drawMarkers();
});
},
drawGlobe() {
Promise.all([json("./world-110m.json")]).then(([worldData, error]) => {
// Do your stuff. Content of both files is now available in stations and svg
this.svg
.selectAll(".segment")
.data(feature(worldData, worldData.objects.countries).features)
.enter()
.append("path")
.attr("class", "segment")
.attr("d", this.path)
.style("stroke", "#888")
.style("stroke-width", "1px")
.style("fill", (d, i) => "#e5e5e5")
.style("opacity", ".6");
this.drawMarkers();
});
},
drawMarkers() {
const markers = this.markerGroup.selectAll("circle").data(this.locations);
markers
.enter()
.append("circle")
.merge(markers)
.attr("cx", (d) => this.projection([d.longitude, d.latitude])[0])
.attr("cy", (d) => this.projection([d.longitude, d.latitude])[1])
.attr("fill", (d) => {
const coordinate = [d.longitude, d.latitude];
var gdistance = d3.geoDistance(coordinate, this.projection.invert(this.center));
return gdistance > 1.57 ? "none" : "steelblue";
})
.attr("r", 7);
this.markerGroup.each(function() {
this.parentNode.appendChild(this);
});
},
drawGraticule() {
const graticule = d3.geoGraticule().step([10, 10]);
this.svg
.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", this.path)
.style("fill", "#fff")
.style("stroke", "#ccc");
},
},
};
</script>
<style></style>
错误如下图所示:
我该如何解决?在此配置中它不起作用。
谢谢
我解决了我的问题,记得在 Javascript 中,当我们在其他函数中工作时,有时“this”元素并不总是我们所期望的。
所以我需要做的是将“this”对象保存在一个变量中并使用该变量来执行我需要的操作:
var x = this;
d3.timer(function(elapsed) {
x.projection.rotate([
x.config.speed * elapsed - 120,
x.config.verticalTilt,
x.config.horizontalTilt,
]);
x.svg.selectAll("path").attr("d", this.path);
x.drawMarkers();
});