在d3缩放中更改矩形尺寸

时间:2015-01-05 10:50:36

标签: javascript d3.js zoom

我正在使用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;
            })



}

1 个答案:

答案 0 :(得分:0)

如果您不希望通过缩放行为更新yScale,只需删除行.y(yScale),您就应该好了。

缩放行为将简单构建:

var zoom = d3.behavior.zoom()
    .x(xScale)
    .scaleExtent([1,100])
    .scale([50])
    .on("zoom", zoomed);

,它只会更新xScale