Tôi đang sử dụng d3 v4 (4.12.0).Tạo trục ngang vô tận với d3 v4
Tôi có vùng chứa SVG mà tôi vẽ một trục ngang đơn giản (trục x, thang đo tuyến tính) phản ứng với việc di chuột bằng chuột.
Tôi muốn mô phỏng trục ngang "vô hạn" hoặc "vô tận". Bằng cách này, tôi có nghĩa là tôi chỉ muốn tải và hiển thị một phần nhỏ của tập dữ liệu rất lớn và chỉ vẽ đủ trục hiển thị tập hợp con rất nhỏ các phần tử từ tập hợp lớn này.
Giả sử tôi có trục ngang hiển thị 10 điểm dữ liệu từ một mảng lớn các đối tượng. Tôi giữ một tham số offset
bắt đầu từ 0, để hiển thị mười điểm đầu tiên của mảng này.
thủ tục của tôi:
Khi tôi di chuyển trục sang trái đủ xa để hiển thị 11 và điểm dữ liệu tiếp theo, tôi sau đó:
Cập nhật tham số
offset
để phản ánh bao nhiêu đơn vị tôi đã dịchcập nhật quy mô trục x, dựa trên các giá trị bù đắp mới
Re vẽ các nhãn trục với phạm vi quy mô được cập nhật của (
x_scale
)Dịch các yếu tố nhóm chứa các trục bằng của số điểm ảnh đại diện cho một đơn vị trên trục (
scroller_element_width
)
nỗ lực của tôi làm việc lên bước 3. Quá trình này có vẻ không thành công ở bước 4, trong đó bản dịch cuối cùng của trục không bao giờ xảy ra.
Toàn bộ trục được di chuyển sang trái và nó có các nhãn mới, nhưng nó không di chuyển sang phải với các nhãn được cập nhật đó - về cơ bản nó rơi khỏi trang.
Tôi muốn hỏi chuyên gia d3 ở đây tại sao bước này không thành công và tôi có thể làm gì để khắc phục sự cố này.
Dưới đây là chức năng thu hút các trục và móc lên sự kiện zoom:
renderScroller() {
console.log("renderScroller called");
if ((this.state.scrollerWidth == 0) || (this.state.scrollerHeight == 0)) return;
const self = this;
const scroller = this.scrollerContainer;
const scroller_content = this.scrollerContent;
const scroller_width = this.state.scrollerWidth;
const scroller_height = this.state.scrollerHeight;
var offset = 0,
limit = 10,
current_index = 10;
var min_translate_x = 0,
max_translate_x;
var scroller_data = Constants.test_data.slice(offset, limit);
var x_extent = d3.extent(scroller_data, function(d) { return d.window; });
var y_extent = [0, d3.max(scroller_data, function(d) { return d.total; })];
var x_scale = d3.scaleLinear();
var y_scale = d3.scaleLinear();
var x_axis_call = d3.axisTop();
x_scale.domain(x_extent).range([0, scroller_width]);
y_scale.domain(y_extent).range([scroller_height, 0]);
x_axis_call.scale(x_scale);
d3.select(scroller_content)
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + [0, scroller_height] + ")")
.call(x_axis_call);
var scroller_element_width = parseFloat(scroller_width/(x_scale.domain()[1] - x_scale.domain()[0]));
var pan = d3.zoom()
.on("zoom", function() {
var t = parseSvg(d3.select(scroller_content).attr("transform"));
var x_offset = parseFloat((t.translateX + d3.event.transform.x)/scroller_element_width);
//
// lock scale and prevent y-axis pan
//
d3.event.transform.y = 0;
if (d3.event.transform.k == 1) {
d3.event.transform.x = (x_offset > 0) ? 0 : d3.event.transform.x;
}
else {
d3.event.transform.k = 1;
d3.event.transform.x = t.translateX;
}
d3.select(scroller_content).attr("transform", d3.event.transform);
t = parseSvg(d3.select(scroller_content).attr("transform"));
x_offset = parseFloat(t.translateX/scroller_element_width);
var test_offset = Math.abs(parseInt(x_offset));
if (test_offset != offset) {
scroller_data = updateScrollerData(test_offset);
x_extent = d3.extent(scroller_data, function(d) { return d.window; });
y_extent = [0, d3.max(scroller_data, function(d) { return d.total; })];
x_scale.domain(x_extent).range([0, scroller_width]);
y_scale.domain(y_extent).range([scroller_height, 0]);
x_axis_call.scale(x_scale);
//
// update axis labels
//
d3.select(scroller_content)
.selectAll(".x.axis")
.call(x_axis_call);
//
// shift the axis backwards to simulate an endless horizontal axis
//
var pre_shift = parseSvg(d3.select(scroller_content).attr("transform"));
console.log("pre_shift", pre_shift.translateX);
console.log("scroller_element_width", scroller_element_width);
var expected_post_shift = pre_shift.translateX + scroller_element_width;
console.log("(expected) post_shift", expected_post_shift);
d3.zoom().translateBy(d3.select(scroller_content), expected_post_shift, 0);
//
// observed and expected translate values do not match!
//
var post_shift = parseSvg(d3.select(scroller_content).attr("transform"));
console.log("(observed) post_shift", post_shift.translateX);
}
});
d3.select(scroller).call(pan);
max_translate_x = this.state.scrollerWidth - x_scale(x_extent[1]);
d3.zoom().translateBy(d3.select(scroller), max_translate_x, 0);
// fetch test data
function updateScrollerData(updated_offset) {
offset = updated_offset;
return Constants.test_data.slice(updated_offset - 1, updated_offset + limit - 1);
}
}
Đây là một chức năng trong một bộ phận Phản ứng. Những thứ Phản ứng không phải là quá phù hợp, nhưng ở đây là render()
chức năng của thành phần đó, để hiển thị SVG phụ huynh và nhóm trẻ yếu tố:
render() {
return (
<svg
className="scroller"
ref={(scroller) => { this.scrollerContainer = scroller; }}
width={this.state.scrollerWidth}
height={this.state.scrollerHeight}>
<g
className="scroller-content"
ref={(scrollerContent) => { this.scrollerContent = scrollerContent; }}
/>
</svg>
);
}
Như đã trình bày, các scrollerContainer
ref là SVG có chứa các nguyên tố nhóm scrollerContent
. Điều này scrollerContent
là những gì có chứa trục ngang.
Khi xoay hoặc cuộn trục x, các phép biến đổi được áp dụng cho scrollerContent
.
Để nhận thông số chuyển đổi, tôi đang sử dụng phương thức trợ giúp parseSvg
từ d3-interpolate
, tức làqua ES6:
import * as d3 from 'd3';
import { parseSvg } from "d3-interpolate/src/transform/parse";
Để hoàn chỉnh, đây là một đoạn dữ liệu thử nghiệm:
export const test_data = [
{
"total": 29.86,
"signal": [
4.842,
1.608,
1.837,
3.052,
1.677,
0.8041,
3.09,
1.813,
2.106,
2.38,
1.773,
0.8128,
2.047,
1.658,
0.3588
],
"window": 0,
"chr": "chr1"
},
{
"total": 35.67,
"signal": [
0.6111,
1.995,
0.5715,
2.51,
3.318,
1.523,
3.94,
2.743,
4.445,
0.759,
4.938,
2.61,
3.379,
1.27,
1.057
],
"window": 1,
"chr": "chr1"
},
{
"total": 39.14,
"signal": [
0.0589,
0.1608,
2.426,
4.673,
3.511,
3.912,
2.809,
4.197,
4.648,
2.069,
2.84,
3.878,
0.2681,
3.622,
0.06911
],
"window": 2,
"chr": "chr1"
},
{
"total": 37.45,
"signal": [
2.688,
1.235,
2.358,
1.994,
1.541,
1.189,
0.8078,
4.872,
2.287,
4.266,
2.24,
3.349,
3.519,
1.896,
3.21
],
"window": 3,
"chr": "chr1"
},
{
"total": 47.17,
"signal": [
3.338,
3.613,
3.872,
1.166,
1.828,
4.24,
1.476,
4.025,
4.144,
4.922,
2.183,
2.701,
3.825,
4.346,
1.494
],
"window": 4,
"chr": "chr1"
},
{
"total": 41.7,
"signal": [
0.2787,
1.74,
0.7557,
4.236,
2.865,
4.542,
4.113,
1.265,
4.826,
3.731,
4.931,
2.392,
2.014,
0.6566,
3.352
],
"window": 5,
"chr": "chr1"
},
{
"total": 31.43,
"signal": [
3.025,
4.399,
1.001,
4.859,
0.9173,
2.851,
2.916,
1.821,
1.228,
1.646,
0.1008,
2.09,
2.502,
0.1476,
1.924
],
"window": 6,
"chr": "chr1"
},
{
"total": 38.23,
"signal": [
1.123,
1.972,
0.5079,
4.808,
0.5669,
4.647,
2.598,
1.874,
0.8699,
4.876,
3.981,
1.503,
4.683,
2.853,
1.366
],
"window": 7,
"chr": "chr1"
},
{
"total": 44.2,
"signal": [
3.895,
0.7457,
2.208,
1.837,
3.219,
3.98,
3.494,
4.225,
3.117,
3.162,
3.171,
2.449,
0.1419,
3.745,
4.807
],
"window": 8,
"chr": "chr1"
},
{
"total": 36.33,
"signal": [
0.3164,
2.753,
4.094,
2.237,
4.748,
2.483,
1.541,
4.113,
0.1874,
3.71,
1.313,
0.221,
2.736,
1.208,
4.671
],
"window": 9,
"chr": "chr1"
},
{
"total": 43.05,
"signal": [
1.924,
0.4136,
3.057,
4.686,
1.263,
0.1333,
0.8786,
4.715,
4.845,
4.282,
2.112,
4.597,
3.822,
1.322,
4.999
],
"window": 10,
"chr": "chr1"
},
{
"total": 31.28,
"signal": [
4.216,
0.6655,
2.078,
1.235,
0.5526,
1.556,
1.005,
3.196,
1.907,
4.932,
0.006601,
1.269,
3.964,
4.608,
0.09109
],
"window": 11,
"chr": "chr1"
},
{
"total": 48.3,
"signal": [
4.469,
1.138,
3.958,
2.801,
3.404,
4.988,
2.649,
3.818,
3.284,
0.9281,
3.982,
0.496,
4.28,
3.258,
4.845
],
"window": 12,
"chr": "chr1"
},
{
"total": 42.1,
"signal": [
1.087,
3.127,
0.493,
3.276,
4.195,
1.561,
2.638,
4.897,
3.675,
4.937,
0.05847,
4.272,
2.33,
1.776,
3.776
],
"window": 13,
"chr": "chr1"
},
{
"total": 40.1,
"signal": [
1.275,
4.574,
2.805,
1.646,
0.8759,
4.948,
3.637,
3.227,
2.259,
2.983,
2.905,
4.134,
3.133,
0.08384,
1.617
],
"window": 14,
"chr": "chr1"
},
{
"total": 50.31,
"signal": [
2.228,
0.7037,
4.977,
1.143,
2.506,
4.348,
4.344,
3.998,
4.213,
2.745,
4.374,
3.411,
4.504,
4.417,
2.396
],
"window": 15,
"chr": "chr1"
},
{
"total": 34.7,
"signal": [
2.729,
3.891,
3.873,
2.973,
0.1487,
1.573,
1.781,
2.788,
2.191,
2.912,
1.355,
2.582,
2.374,
3.164,
0.3641
],
"window": 16,
"chr": "chr1"
},
{
"total": 32.89,
"signal": [
3.619,
2.119,
1.854,
4.083,
0.9916,
0.5065,
0.8343,
4.835,
1.723,
3.926,
2.675,
2.281,
0.1531,
2.239,
1.049
],
"window": 17,
"chr": "chr1"
},
{
"total": 38.94,
"signal": [
1.976,
1.587,
3.808,
0.1173,
3.823,
4.349,
3.652,
1.308,
3.434,
3.855,
1.622,
0.2916,
2.382,
3.091,
3.647
],
"window": 18,
"chr": "chr1"
},
{
"total": 34.18,
"signal": [
0.339,
3.695,
3.108,
3.267,
0.08282,
3.53,
2.316,
1.11,
4.504,
4.111,
0.007636,
0.5581,
2.985,
1.707,
2.857
],
"window": 19,
"chr": "chr1"
},
{
"total": 29.62,
"signal": [
2.695,
0.8477,
4.417,
3.012,
2.454,
2.686,
0.6529,
0.2275,
1.052,
0.2092,
2.968,
3.268,
0.7144,
0.4441,
3.973
],
"window": 20,
"chr": "chr1"
}
];
Hy vọng rằng điều này cho thấy tất cả các công việc cần thiết để giải thích vấn đề. Cảm ơn lời khuyên hoặc hướng dẫn.
vui lòng cung cấp axample đang làm việc – KEKUATAN