Javascript 在d3缩放中更改矩形尺寸
我正在使用d3构建一个钢琴卷编辑器(看起来有点像)。我需要始终将矩形捕捉到网格上,以便在平移或缩放时,形状将保持相对于网格线。我进进出出时是否重新绘制垂直网格线并不重要,但水平网格线的数量应始终保持不变,并且矩形形状始终锁定。这里可以看到一个不太有效的例子: 我可以看到很多d3缩放类型的例子,但我找不到任何东西来解决这种问题。我想我只是不理解在使用缩放功能时如何正确缩放形状。此外,在试图让这项工作,我注意到平移和缩放似乎已经变得有点不可靠,不知道为什么 无论如何,如果有人对如何解决这个问题有任何想法,我们将不胜感激。JSFIDLE上的代码如下所示: 更新:只是为了(希望!)澄清-水平轴和垂直轴都需要缩放。约束条件是,水平轴网线的数量需要保持不变,并且形状必须锁定在轴网线上,以便尺寸永远不变。如果矩形的宽度和高度均为1,则缩放时始终需要保留该值Javascript 在d3缩放中更改矩形尺寸,javascript,d3.js,zooming,Javascript,D3.js,Zooming,我正在使用d3构建一个钢琴卷编辑器(看起来有点像)。我需要始终将矩形捕捉到网格上,以便在平移或缩放时,形状将保持相对于网格线。我进进出出时是否重新绘制垂直网格线并不重要,但水平网格线的数量应始终保持不变,并且矩形形状始终锁定。这里可以看到一个不太有效的例子: 我可以看到很多d3缩放类型的例子,但我找不到任何东西来解决这种问题。我想我只是不理解在使用缩放功能时如何正确缩放形状。此外,在试图让这项工作,我注意到平移和缩放似乎已经变得有点不可靠,不知道为什么 无论如何,如果有人对如何解决这个问题有任何
//Data for note shapes
var noteData = [
{frequency: 3, duration:1, startPoint: 1},
{frequency: 6, duration:1, startPoint: 2},
{frequency: 5, duration:1, startPoint: 3},
{frequency: 4, duration:1, startPoint: 4}
];
margin = {
top: 20,
right: 20,
bottom: 20,
left: 45
};
width = 400 - margin.left - margin.right;
height = 200 - margin.top - margin.bottom;
//SCALES
var xScale = d3.scale.linear()
.domain([0,width])
.range([0, width])
var yScale = d3.scale.linear()
.domain([0,width])
.range([0, height]);
var heightScale = d3.scale.linear()
.domain([0,100])
.range([0,height]);
//Set up zoom
var zoom = d3.behavior.zoom()
.x(xScale)
.y(yScale)
.scaleExtent([1,100])
.scale([50])
.on("zoom", zoomed);
// Create SVG space and centre it
svg = d3.select('#chart')
.append("svg:svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
// Append a rect on top
var rect = svg.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot");
var noteRange = d3.range(0,88);
var measureRange = d3.range(0,16);
var make_x_axis = function () {
return d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(10);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(yScale)
.orient("left")
.tickValues(noteRange);
};
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(10);
//.tickValues([2,5,7,9]);
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.tickValues(noteRange);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.append("g")
.attr("class", "y grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
var rectGroup = svg.append("g")
var notes = rectGroup
.selectAll("rect")
.data(noteData)
.enter()
.append("rect")
.attr("x",function(d){
return xScale(d.startPoint)
})
.attr("y",function(d){
return yScale(d.frequency)
})
.attr("width",function(d) {
return 50;
})
.attr('class', 'rect')
.attr("height", function(d) {
return 23;
})
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.select(".x.grid")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat(""));
svg.select(".y.grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
rectGroup.selectAll("rect")
.attr('class', 'rect')
.attr("x",function(d){
return xScale(d.startPoint);
})
.attr("y",function(d){
return yScale(d.frequency);
})
.attr('width', function(d) {
return 50;
})
.attr("height", function(d) {
return 23;
})
}
如果不希望缩放行为更新
yScale
,只需删除.y(yScale)
行即可
缩放行为将简单地构造为:
var zoom = d3.behavior.zoom()
.x(xScale)
.scaleExtent([1,100])
.scale([50])
.on("zoom", zoomed);
它只会更新
xScale
是否要缩放水平轴,而保持垂直轴比例不变?这可能与您的问题无关,但为什么您要使用一组D3轴作为视觉轴,并在每次缩放时为网格创建一组全新的轴?作为补充,您可以重构此代码以删除大量重复,并使您自己和StackOverflow上的其他人更容易看到发生了什么。抱歉,我可能解释得很糟糕。我很高兴水平轴和垂直轴都可以缩放。约束条件是,水平轴网线的数量需要保持不变,并且形状必须锁定在轴网线上,以便形状尺寸永远不会更改。问题是,当我缩放形状时,形状没有保持正确的尺寸(即保留它们开始时的宽度和高度)。我已经更新了上面的小提琴,使它更直观一点。您可以看到底部的矩形以1的高度和宽度开始,它不再捕捉到网格线。@Couchand-我正在创建新的轴,因为我对这方面的了解还不够!将尝试重构代码