gpt4 book ai didi

javascript - 如何使用多个 y 轴正确放大图表

转载 作者:行者123 更新时间:2023-11-29 22:46:35 24 4
gpt4 key购买 nike

我为我的图表实现了缩放功能,可以通过拖动并释放图表的某个区域来放大该区域。我的 fiddle 可以访问 here .

随着蓝线和左轴的更新,蓝线的缩放功能正常工作。但是,当红线放大时,右轴不会更新。我已经为右轴硬编码了一个从 0 到 200 的域,所以每当我放大域时,域就会从 0 变为 200,而不是正确的放大域。右侧轴域的代码应该是什么,以便它在缩放期间得到更新?非常感谢任何帮助!

    var data = [ {x: 0, y: 0, y1: 0}, {x: 1, y: 30, y1: 100}, {x: 2, y: 40, y1: 200},
{x: 3, y: 60, y1: 300}, {x: 4, y: 70, y1: 400}, {x: 5, y: 90, y1: 500} ];

const margin = {
left: 20,
right: 20,
top: 20,
bottom: 80
};

const svg = d3.select('svg');
svg.selectAll("*").remove();

const width = 200 - margin.left - margin.right;
const height = 200 - margin.top - margin.bottom;

const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);

var x = d3.scaleLinear()
.domain([0, d3.max(data, function(d){ return d.x; })])
.range([0,width])
.nice();

var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d){ return d.y; })])
.range([0,height])
.nice();

var y1 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return d.y1; })])
.range([0, height])
.nice();

const xAxis = d3.axisTop()
.scale(x)
.ticks(5)
.tickPadding(3)
.tickSize(-height)

const yAxis = d3.axisLeft()
.scale(y)
.ticks(5)
.tickPadding(3)
.tickSize(-width);

const yAxis1 = d3.axisRight()
.scale(y1)

svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(20,20)")
.call(xAxis);

svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(20,20)")
.call(yAxis);

svg.append("g")
.attr("class", "y1 axis")
.attr("transform", "translate(185,20)")
.call(yAxis1);


var lineFunction = d3.line()
.x(function(d) {return x(d.x); })
.y(function(d) {return y(d.y); })
.curve(d3.curveLinear);

var lineFunctionOne = d3.line()
.x(function(d) {return x(d.x); })
.y(function(d) {return y1(d.y1); })
.curve(d3.curveLinear);

//defining and plotting the lines
var path = g.append("path")
.attr("class", "path1")
.attr("id", "blueLine")
.attr("d", lineFunction(data))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none")
.attr("clip-path", "url(#clip)");

var path1 = g.append("path")
.attr("class", "path2")
.attr("id", "redLine")
.attr("d", lineFunctionOne(data))
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("fill", "none")
.attr("clip-path", "url(#clip)");

//************* Zoom ***************
//add brushing
var brush = d3.brush().extent([[0, 0], [width, height]]).on("end", brushended),
idleTimeout,
idleDelay = 350;
g.append("g")
.attr("class", "brush")
.call(brush);

// Add a clipPath: everything out of this area won't be drawn when chart is zoomed in
var clip = svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);

function brushended() {

var s = d3.event.selection;
//If no selection, re-initialize chart on double click. Otherwise, update x-axis and y-axis domain
if (!s) {
// This allows to wait a little bit
if (!idleTimeout) return idleTimeout = setTimeout(idled, 350);
x.domain(d3.extent(data, function (d) { return d.x; })).nice();
y.domain(d3.extent(data, function (d) { return d.y; })).nice();
y1.domain(d3.extent(data, function (d) { return d.y1; })).nice();
} else {
x.domain([s[0][0], s[1][0]].map(x.invert, x));
y.domain([s[0][1], s[1][1]].map(y.invert, y));
y1.domain([0, 200]); //hardcoded domain
//This removes the grey brush area as soon as the selection has been done
g.select(".brush").call(brush.move, null)
}
zoom();
}

function idled() {
idleTimeout = null;
}

function zoom() {
var t = svg.transition().duration(750);
svg.select(".x.axis").transition(t).call(xAxis);
svg.select(".y.axis").transition(t).call(yAxis);
svg.select(".y1.axis").transition(t).call(yAxis1);
svg.select(".path1").transition(t).attr("d", lineFunction(data));
svg.select(".path2").transition(t).attr("d", lineFunctionOne(data));
}

最佳答案

我对你的问题感到困惑......你需要做的就是你在上面的行中所做的同样的事情:

y1.domain([s[0][1], s[1][1]].map(y1.invert, y));

顺便说一句,你不需要 map 中的 thisArg,它可以只是:

y1.domain([s[0][1], s[1][1]].map(y1.invert));

这是更新后的代码:

var data = [{
x: 0,
y: 0,
y1: 0
}, {
x: 1,
y: 30,
y1: 100
}, {
x: 2,
y: 40,
y1: 200
},
{
x: 3,
y: 60,
y1: 300
}, {
x: 4,
y: 70,
y1: 400
}, {
x: 5,
y: 90,
y1: 500
}
];

const margin = {
left: 20,
right: 20,
top: 20,
bottom: 80
};

const svg = d3.select('svg');
svg.selectAll("*").remove();

const width = 200 - margin.left - margin.right;
const height = 200 - margin.top - margin.bottom;

const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);

var x = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.x;
})])
.range([0, width])
.nice();

var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.y;
})])
.range([0, height])
.nice();

var y1 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.y1;
})])
.range([0, height])
.nice();

const xAxis = d3.axisTop()
.scale(x)
.ticks(5)
.tickPadding(3)
.tickSize(-height)

const yAxis = d3.axisLeft()
.scale(y)
.ticks(5)
.tickPadding(3)
.tickSize(-width);

const yAxis1 = d3.axisRight()
.scale(y1)

svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(20,20)")
.call(xAxis);

svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(20,20)")
.call(yAxis);

svg.append("g")
.attr("class", "y1 axis")
.attr("transform", "translate(185,20)")
.call(yAxis1);


var lineFunction = d3.line()
.x(function(d) {
return x(d.x);
})
.y(function(d) {
return y(d.y);
})
.curve(d3.curveLinear);

var lineFunctionOne = d3.line()
.x(function(d) {
return x(d.x);
})
.y(function(d) {
return y1(d.y1);
})
.curve(d3.curveLinear);

//defining the lines
var path = g.append("path")
.attr("class", "path1")
.attr("id", "blueLine")
.attr("d", lineFunction(data))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none")
.attr("clip-path", "url(#clip)");

var path1 = g.append("path")
.attr("class", "path2")
.attr("id", "redLine")
.attr("d", lineFunctionOne(data))
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("fill", "none")
.attr("clip-path", "url(#clip)");

//************* Zoom ***************
//add brushing
var brush = d3.brush().extent([
[0, 0],
[width, height]
]).on("end", brushended),
idleTimeout,
idleDelay = 350;
g.append("g")
.attr("class", "brush")
.call(brush);

// Add a clipPath: everything out of this area won't be drawn when chart is zoomed in
var clip = svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);

function brushended() {

var s = d3.event.selection;
//If no selection, re-initialize chart on double click. Otherwise, update x-axis and y-axis domain
if (!s) {
// This allows to wait a little bit
if (!idleTimeout) return idleTimeout = setTimeout(idled, 350);
x.domain(d3.extent(data, function(d) {
return d.x;
})).nice();
y.domain(d3.extent(data, function(d) {
return d.y;
})).nice();
y1.domain(d3.extent(data, function(d) {
return d.y1;
})).nice();
} else {
x.domain([s[0][0], s[1][0]].map(x.invert, x));
y.domain([s[0][1], s[1][1]].map(y.invert, y));
y1.domain([s[0][1], s[1][1]].map(y1.invert, y)); //hardcoded domain
//This removes the grey brush area as soon as the selection has been done
g.select(".brush").call(brush.move, null)
}
zoom();
}

function idled() {
idleTimeout = null;
}

function zoom() {
var t = svg.transition().duration(750);
svg.select(".x.axis").transition(t).call(xAxis);
svg.select(".y.axis").transition(t).call(yAxis);
svg.select(".y1.axis").transition(t).call(yAxis1);
svg.select(".path1").transition(t).attr("d", lineFunction(data));
svg.select(".path2").transition(t).attr("d", lineFunctionOne(data));
}
.xy_chart {
position: relative;
left: 50px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg class="xy_chart"></svg>

关于javascript - 如何使用多个 y 轴正确放大图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58314506/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com