我正在使用d3来构建钢琴卷编辑器(看起来有点像this)。我需要将矩形始终捕捉到网格上,这样当我平移或缩放时,形状将保持相对于网格线。当我移入和移出时,垂直网格线是否重绘无关紧要,但水平网格线的数量应始终保持不变,并且矩形形状始终被锁定。在这里可以看到它不能正常工作的一个例子:http://jsfiddle.net/jgab3103/e05qj4hy/
我可以在这个地方看到很多d3缩放类型的例子,但我找不到任何解决这类问题的方法。我想我只是不理解在使用缩放功能时如何正确缩放形状。此外,在试图让这个工作,我注意到平移和缩放似乎已经变得有点不可靠,不知道为什么。
无论如何,如果有人对如何解决这个问题有任何想法,我们将不胜感激。 jsfiddle上的代码如下:
更新:只是为了(希望!)澄清 - 水平和垂直轴都需要缩放。约束是水平网格线的数量需要保持不变,并且形状必须锁定到网格线上,因此尺寸永远不会改变。如果矩形的宽度和高度为1,则在缩放时始终需要保留该矩形。
//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;
})
}
答案 0 :(得分:0)
如果您不希望通过缩放行为更新yScale
,只需删除行.y(yScale)
,您就应该好了。
缩放行为将简单构建:
var zoom = d3.behavior.zoom()
.x(xScale)
.scaleExtent([1,100])
.scale([50])
.on("zoom", zoomed);
,它只会更新xScale
。