我目前正在使用D3 v4。我的x刻度是一个scaleBand,我在这里显示一个国家名称,我的y刻度是scaleTime。当我试图在缩放功能中获得新的xScale时,它会在rescaleX上抛出错误。我在网上查看了很多例子,但所有这些例子都有一个linearScale或scaleTime。
var countryArr = ["USA", "UK", "Poland", "Sweden"];
var firstDay = moment(day).subtract(1, 'days').toDate();
var lastDay = moment(day).add(1, 'days').toDate();
// define scale
var yScale = d3.scaleTime().range([0, width]);
yScale.domain([firstDay, lastDay]);
var xScale = d3.scaleBand().range([0, height]);
xScale.domain(countryArr);
// define zoom
var zoom = d3.zoom()
.scaleExtent([1, 1])
.translateExtent([[margin.left, margin.top], [width, height]])
.on("zoom", zoomed);
d3.select("#main-canvas").call(zoom);
function zoomed() {
//console.log(d3.event.transform.y);
var new_x = d3.event.transform.rescaleX(xScale); // ERROR at this line
var new_y = d3.event.transform.rescaleY(yScale);
}
答案 0 :(得分:3)
在序数(定性)比例中使用rescaleX
毫无意义。 API很清楚:
返回其域已转换的连续比例 x的副本。这是通过首先在比例范围上应用逆x变换,然后应用逆比例来计算相应的域来实现的。 (强调我的)
另外,Bostock(D3创作者)already explained ......
...缩放行为影响附加比例的域,但是在平移和缩放时修改序数比例的域是没有意义的,因为域是离散的。
您可以做的是创建几何缩放而不是语义缩放。
这是一个演示,我使用条形图的this example来添加几何缩放:
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = [{
"letter": "A",
"frequency": 0.08167
}, {
"letter": "B",
"frequency": 0.01492
}, {
"letter": "C",
"frequency": 0.02782
}, {
"letter": "D",
"frequency": 0.04253
}, {
"letter": "E",
"frequency": 0.12702
}, {
"letter": "F",
"frequency": 0.02288
}, {
"letter": "G",
"frequency": 0.02015
}, {
"letter": "H",
"frequency": 0.06094
}, {
"letter": "I",
"frequency": 0.06966
}, {
"letter": "J",
"frequency": 0.00153
}, {
"letter": "K",
"frequency": 0.00772
}, {
"letter": "L",
"frequency": 0.04025
}, {
"letter": "M",
"frequency": 0.02406
}, {
"letter": "N",
"frequency": 0.06749
}, {
"letter": "O",
"frequency": 0.07507
}, {
"letter": "P",
"frequency": 0.01929
}, {
"letter": "Q",
"frequency": 0.00095
}, {
"letter": "R",
"frequency": 0.05987
}, {
"letter": "S",
"frequency": 0.06327
}, {
"letter": "T",
"frequency": 0.09056
}, {
"letter": "U",
"frequency": 0.02758
}, {
"letter": "V",
"frequency": 0.00978
}, {
"letter": "W",
"frequency": 0.0236
}, {
"letter": "X",
"frequency": 0.0015
}, {
"letter": "Y",
"frequency": 0.01974
}, {
"letter": "Z",
"frequency": 0.00074
}];
x.domain(data.map(function(d) {
return d.letter;
}));
y.domain([0, d3.max(data, function(d) {
return d.frequency;
})]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "%"))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Frequency");
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.letter);
})
.attr("y", function(d) {
return y(d.frequency);
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.frequency);
});
var rect = g.append("rect")
.attr("width", width)
.attr("height", height)
.attr("opacity", 0)
.call(d3.zoom()
.scaleExtent([.1, 10])
.on("zoom", zoom));
function zoom() {
g.attr("transform", d3.event.transform);
}

.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}

<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
答案 1 :(得分:2)
正如@gerardofurtado所解释的那样,重新缩放功能对于序数规模几乎没有什么作用。但这里有一个小技巧,我喜欢使用重新缩放序数轴在图形上进行精确缩放。基本上,它独立地缩放轴,然后反向缩放轴的组成部分(线和文本),以便它们不会扭曲:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
<style>
.bar {
fill: steelblue;
}
.bar:hover {
fill: brown;
}
.axis--x path {
display: none;
}
</style>
</head>
<body>
<svg width="400" height="400"></svg>
<script>
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([
[0, 0],
[width, height]
])
.extent([
[0, 0],
[width, height]
])
.on("zoom", zoom);
svg.call(zoom);
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleBand().rangeRound([height, 0]).padding(0.1);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var defs = g.append('defs');
defs
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
defs
.append('clipPath')
.attr('id', 'clipx')
.append('rect')
.attr('x', 0)
.attr('y', height)
.attr('width', width)
.attr('height', margin.bottom);
defs
.append('clipPath')
.attr('id', 'clipy')
.append('rect')
.attr('x', -margin.left)
.attr('y', -10)
.attr('width', margin.left+1)
.attr('height', height+15);
var data = [{
"letter": "A",
"frequency": 'Z'
}, {
"letter": "B",
"frequency": 'Y'
}, {
"letter": "C",
"frequency": 'X'
}, {
"letter": "D",
"frequency": 'W'
}, {
"letter": "E",
"frequency": 'V'
}, {
"letter": "F",
"frequency": 'U'
}, {
"letter": "G",
"frequency": 'T'
}, {
"letter": "H",
"frequency": 'S'
}, {
"letter": "I",
"frequency": 'R'
}, {
"letter": "J",
"frequency": 'Q'
}, {
"letter": "K",
"frequency": 'P'
}, {
"letter": "L",
"frequency": 'O'
}, {
"letter": "M",
"frequency": 'N'
}, {
"letter": "N",
"frequency": 'M'
}, {
"letter": "O",
"frequency": 'L'
}, {
"letter": "P",
"frequency": 'K'
}, {
"letter": "Q",
"frequency": 'J'
}, {
"letter": "R",
"frequency": 'I'
}, {
"letter": "S",
"frequency": 'H'
}, {
"letter": "T",
"frequency": 'G'
}, {
"letter": "U",
"frequency": 'F'
}, {
"letter": "V",
"frequency": 'E'
}, {
"letter": "W",
"frequency": 'D'
}, {
"letter": "X",
"frequency": 'C'
}, {
"letter": "Y",
"frequency": 'B'
}, {
"letter": "Z",
"frequency": 'A'
}];
x.domain(data.map(function(d) {
return d.letter;
}));
y.domain(data.map(function(d) {
return d.frequency;
}));
var xAxis = g.append("g")
.attr('clip-path', 'url(#clipx)')
.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
var yAxis = g.append("g")
.attr('clip-path', 'url(#clipy)')
.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y));
yAxis
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Letters Too");
var bars = g.append("g")
.attr('clip-path', 'url(#clip)')
.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.letter);
})
.attr("y", function(d) {
return y(d.frequency) + y.bandwidth()/2;
})
.attr("width", x.bandwidth())
.attr("height", function(d) {
return height - y(d.frequency);
});
function zoom() {
var t = d3.event.transform;
bars.attr("transform", t);
xAxis.attr("transform", d3.zoomIdentity.translate(t.x, height).scale(t.k));
xAxis.selectAll("text")
.attr("transform",d3.zoomIdentity.scale(1/t.k));
xAxis.selectAll("line")
.attr("transform",d3.zoomIdentity.scale(1/t.k));
yAxis.attr("transform", d3.zoomIdentity.translate(0, t.y).scale(t.k));
yAxis.selectAll("text")
.attr("transform",d3.zoomIdentity.scale(1/t.k));
yAxis.selectAll("line")
.attr("transform",d3.zoomIdentity.scale(1/t.k));
}
</script>
</body>
</html>
&#13;