我正在尝试使我的 D3 图表可拖动,但是当我拖动应用程序时崩溃了。
使用 d3-3d 使其拖动。
错误:
编码:
let sum;
var j = 10,
scale = 8,
scatter = [],
xLine = [],
yLine = [],
zLine = [],
beta = 0,
alpha = 0,
key = function (d) {
return d.id;
},
startAngle = Math.PI / 4,
h = 300,
w = 367,
backgroundDots = [];
var origin = [w * 0.4, h / 2];
var svg = d3
.select(node)
.append("svg")
.attr("class", "nnsContainer")
.attr("width", w)
.attr("height", h)
.on("mouseover", hoverStart)
.on("mouseout", hoverEnd)
.call(
d3.drag()
.on("drag", (event) => dragged(event))
.on("start", (event) => dragStart(event))
.on("end", (event) => dragEnd(event))
)
.append("g");
var mx, my, mouseX, mouseY;
var borderPath = svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", h)
.attr("width", w)
.style("stroke", "black")
.style("fill", "none")
.style("stroke-width", 0.3);
// center origin at target word or centroid of points
var center;
if (!this.state.query_word) {
center = {};
for (const dim of ["x", "y", "z"]) {
sum = radarChartData.query[dim];
for (const nn of radarChartData.neighbors) {
sum += nn[dim];
}
center[dim] = sum / (radarChartData.neighbors.length + 1);
}
} else {
center = {
x: radarChartData.query.x,
y: radarChartData.query.y,
z: radarChartData.query.z,
};
}
for (const dim of ["x", "y", "z"]) {
radarChartData.query[dim] -= center[dim];
for (var i = 0; i < radarChartData.neighbors.length; i++) {
radarChartData.neighbors[i][dim] -= center[dim];
}
}
var cursorStatus = {
hovering: false,
dragging: false,
};
var cursorUpdate = function (cursorStatus) {
if (cursorStatus.dragging) {
document.querySelector("html, body").style.cursor = "grabbing";
} else if (cursorStatus.hovering) {
document.querySelector("html, body").style.cursor = "grab";
} else {
document.querySelector("html, body").style.cursor = "auto";
}
};
// scale zoom level for size of viz, and range of data
var query_magnitude = Math.sqrt(
this.state.radarChartData.query.x ** 2 +
this.state.radarChartData.query.y ** 2 +
this.state.radarChartData.query.z ** 2
);
var mag_max = query_magnitude;
for (var i = 0; i < this.state.radarChartData.neighbors.length; i++) {
var pt = this.state.radarChartData.neighbors[i];
var magnitude = Math.sqrt(pt.x ** 2 + pt.y ** 2 + pt.z ** 2);
if (magnitude > mag_max) {
mag_max = magnitude;
}
}
var zoom_scale = d3.scaleLinear().domain([100, 300]).range([50, 150]);
scale = zoom_scale(h) / mag_max;
// scale dots & labels for size of viz and distance from camera
var minFontScale = d3.scaleLinear().domain([80, 160]).range([7, 10]);
minFontScale.clamp(true);
var maxFontScale = d3.scaleLinear().domain([80, 208]).range([11, 19]);
maxFontScale.clamp(true);
var zToFont = d3
.scaleLinear()
.domain([-mag_max, mag_max])
.range([minFontScale(h), maxFontScale(h)]);
// 100 is just arbitrary high val, we just need to clamp min size
var positive = d3.scaleLinear().domain([0.5, 100]).range([0.5, 100]);
positive.clamp(true);
var fontSize = function (d) {
return positive(zToFont(d.rotated.z));
};
var pointSize = function (d) {
return fontSize(d) / 3;
};
var point3d = _3d()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
.z(function (d) {
return d.z;
})
.origin(origin)
.rotateY(startAngle)
.rotateX(-startAngle)
.scale(scale);
var yScale3d = _3d()
.shape("LINE_STRIP")
.origin(origin)
.rotateY(startAngle)
.rotateX(-startAngle)
.scale(scale);
function processData(data, tt) {
console.log(data)
/* ----------- POINTS ----------- */
var points = svg.selectAll("circle.main").data(data[0], key);
points
.enter()
.append("circle")
.attr("class", "_3d main")
.attr("opacity", 0)
.attr("cx", posPointX)
.attr("cy", posPointY)
.merge(points)
.attr("r", function (d) {
return pointSize(d) + "px";
})
.style("fill", function (d) {
if (d.id == "point_0") {
return "#8525e5";
} else {
return "#4e3864";
}
})
.attr("opacity", 0.7)
.attr("cx", posPointX)
.attr("cy", posPointY);
points.exit().remove();
/* ----------- GRAY BG POINTS ----------- */
var pointsBG = svg.selectAll("circle.bg").data(data[4], key);
pointsBG
.enter()
.append("circle")
.attr("class", "_3d bg")
.attr("opacity", 0)
.attr("cx", posPointX)
.attr("cy", posPointY)
.merge(pointsBG)
.attr("r", function (d) {
return pointSize(d) + "px";
})
.attr("fill", "#4e3864")
// disappear the points if they're closer than origin
.attr("opacity", function (d) {
if (d.rotated.z < 0) {
return 0.25;
} else {
return 0;
}
})
.attr("cx", posPointX)
.attr("cy", posPointY);
pointsBG.exit().remove();
/* ----------- POINT TEXT ----------- */
var pointText = svg.selectAll("g.pointText").data(data[0]);
pointText
.enter()
.append("g")
.attr("class", "_3d pointText")
.merge(pointText)
.attr("transform", function (d) {
return "translate(" + d.projected.x + ", " + d.projected.y + ")";
})
.selectAll("*")
.remove();
pointText
.append("text")
.attr("dx", function (d) {
return pointSize(d) * 1.2 + "px";
})
.attr("dy", function (d) {
return pointSize(d) * 1.2 + "px";
})
.attr("class", "shadow")
.text(function (d) {
return d.label;
})
.attr("font-size", function (d) {
return fontSize(d) + "px";
});
pointText
.append("text")
.attr("dx", function (d) {
return pointSize(d) * 1.2 + "px";
})
.attr("dy", function (d) {
return pointSize(d) * 1.2 + "px";
})
.text(function (d) {
return d.label;
})
.attr("font-size", function (d) {
return fontSize(d) + "px";
})
.style("fill", "#fff");
pointText.exit().remove();
/* ----------- x-Scale ----------- */
var xScale = svg.selectAll("path.xScale").data(data[1]);
xScale
.enter()
.append("path")
.attr("class", "_3d xScale")
.merge(xScale)
.attr("stroke", "red")
.attr("stroke-width", 0.75)
.attr("opacity", 0.5)
.attr("d", yScale3d.draw);
xScale.exit().remove();
/* ----------- y-Scale ----------- */
var yScale = svg.selectAll("path.yScale").data(data[2]);
yScale
.enter()
.append("path")
.attr("class", "_3d yScale")
.merge(yScale)
.attr("stroke", "green")
.attr("stroke-width", 0.75)
.attr("opacity", 0.5)
.attr("d", yScale3d.draw);
yScale.exit().remove();
/* ----------- z-Scale ----------- */
var zScale = svg.selectAll("path.zScale").data(data[3]);
zScale
.enter()
.append("path")
.attr("class", "_3d zScale")
.merge(zScale)
.attr("stroke", "blue")
.attr("stroke-width", 0.75)
.attr("opacity", 0.5)
.attr("d", yScale3d.draw);
zScale.exit().remove();
svg.selectAll("._3d").sort(_3d().sort);
}
function posPointX(d) {
return d.projected.x;
}
function posPointY(d) {
return d.projected.y;
}
function init() {
var cnt = 0,
scatter = [],
yLine = [];
console.log(radarChartData, "init2");
scatter.push({
x: radarChartData.query.x,
y: radarChartData.query.y,
z: radarChartData.query.z,
label: radarChartData.query.word,
id: "point_0",
});
for (var i = 0; i < radarChartData.neighbors.length; i++) {
scatter.push({
x: radarChartData.neighbors[i].x,
y: radarChartData.neighbors[i].y,
z: radarChartData.neighbors[i].z,
label: radarChartData.neighbors[i].word,
id: "point_" + (i + 1),
});
}
backgroundDots = [];
function backgroundDotRange() {
return (Math.random() * mag_max * 2 - mag_max) * 4;
}
for (var i = 0; i < 10; i++) {
backgroundDots.push({
x: backgroundDotRange(),
y: backgroundDotRange(),
z: backgroundDotRange(),
});
}
xLine = [
[0, 0, 0],
[j, 0, 0],
];
yLine = [
[0, 0, 0],
[0, -j, 0],
];
zLine = [
[0, 0, 0],
[0, 0, j],
];
var data = [
point3d(scatter),
yScale3d([xLine]),
yScale3d([yLine]),
yScale3d([zLine]),
point3d(backgroundDots),
];
processData(data, 1000);
processData(data, 1000);
// text wasn't appearing until dragged, so added this extra rotate
point3d.rotateY(startAngle).rotateX(startAngle)(scatter);
}
function hoverStart() {
cursorStatus.hovering = true;
cursorUpdate(cursorStatus);
}
function hoverEnd() {
cursorStatus.hovering = false;
cursorUpdate(cursorStatus);
}
function dragStart(event) {
mx = d3.event.x;
my = d3.event.y;
console.log(event, 'event1')
cursorStatus.dragging = true;
cursorUpdate(cursorStatus);
}
function dragged(event) {
let mouseX = mouseX || 0;
let mouseY = mouseY || 0;
let beta = ((d3.event.x - mx + mouseX) * Math.PI) / 230;
let alpha = (((d3.event.y - my + mouseY) * Math.PI) / 230) * -1;
console.log(beta, alpha)
var data = [
point3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)(scatter),
yScale3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)([xLine]),
yScale3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)([yLine]),
yScale3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)([zLine]),
point3d.rotateY(beta + startAngle).rotateX(alpha - startAngle)(backgroundDots)
];
processData(data, 0);
}
function dragEnd(event) {
mouseX = d3.event.x - mx + mouseX;
mouseY = d3.event.y - my + mouseY;
cursorStatus.dragging = false;
cursorUpdate(cursorStatus);
}
init();
向组件添加图表:<RD3Component data={this.state.d3} />
我想这些问题涉及到React
,因为我正在传输纯JS
代码,所以效果很好。
也许有人面临上述问题?
版本:
- D3 4.0.0
- 反应 16
- React-D3-库 1.1.8