【问题标题】:D3.js Set initial zoom levelD3.js 设置初始缩放级别
【发布时间】:2013-04-17 04:47:54
【问题描述】:

我设置了几个图表来放大容器,效果很好。但是,在初始加载时,缩放级别太接近了。有没有一种方法可以设置初始缩放级别以避免必须先缩小?我熟悉.scale() 方法,但没有任何运气来实现它。这是要走的路还是我缺少什么?

这是我迄今为止关于缩放的内容:

var margin = {top: 20, right: 120, bottom: 20, left: 120},
    width = 50000 - margin.right - margin.left,
    height = 120000 - margin.top - margin.bottom;

var x = d3.scale.linear()
    .domain([0, width])
    .range([0, width]);

var y = d3.scale.linear()
    .domain([0, height])
    .range([height, 0]);

var tree = d3.layout.tree()
    .size([height, width])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x, d.y]; });

function zoom(d) {        
  svg.attr("transform",
      "translate(" + d3.event.translate + ")"+ " scale(" + d3.event.scale + ")");
}

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
    .attr("pointer-events", "all")
    .call(d3.behavior.zoom()
        .x(x)
        .y(y)
        .scaleExtent([0,8])
        .on("zoom", zoom))
        .append('g');

svg.append('rect')
    .attr('width', width*5)
    .attr('height', height)
    .attr('border-radius', '20')
    .attr('fill', 'sienna');

【问题讨论】:

  • 既然您使用 SVG 转换 scale 进行缩放,为什么不静态设置一个缩放值来提供您想要的缩放级别?
  • 听起来很棒!我该怎么做?
  • Lars,scale 值到底是怎么静态设置的?

标签: javascript d3.js zooming


【解决方案1】:

D3v4 答案

如果您在这里寻找相同但使用 D3 v4,

var zoom = d3.zoom().on("zoom", function(){
    svg.attr("transform", d3.event.transform);
});

vis = svg.append("svg:svg")
     .attr("width", width)
     .attr("height", height)
     .call(zoom) // here
     .call(zoom.transform, d3.zoomIdentity.translate(100, 50).scale(0.5))
     .append("svg:g")
     .attr("transform","translate(100,50) scale(.5,.5)");

【讨论】:

  • 无法让此解决方案在 d3 v5 上运行。你知道有什么变化吗?
【解决方案2】:

我终于通过将初始变换和缩放行为设置为相同的值来实现这一点。

var zoom = d3.behavior.zoom().translate([100,50]).scale(.5);

vis = svg.append("svg:svg")
     .attr("width", width)
     .attr("height", height)
     .call(zoom.on("zoom",zooming))
           .append("svg:g")
           .attr("transform","translate(100,50)scale(.5,.5)");  

【讨论】:

    【解决方案3】:

    将此答案添加为已接受答案的附录,以防任何人仍有问题:

    让这件事变得非常容易理解的是 here

    话虽如此,我设置了三个变量:

    缩放、缩放宽度和缩放高度

    scale是你希望缩放的初始比例,然后

    zoomWidth 和 zoomHeight 定义如下:

    zoomWidth = (width-scale*width)/2
    zoomHeight = (height-scale*height)/2
    

    其中 width 和 height 是 "vis" svg 元素的宽度和高度

    然后将上面的翻译修改为:

    .attr("transform", "translate("+zoomWidth+","+zoomHeight+") scale("+scale+")")
    

    还有缩放功能:

    d3.behavior.zoom().translate([zoomWidth,zoomHeight]).scale(scale)
    

    这样做可以有效地确保您的元素在加载可视化时缩放并居中。

    如果这对您有帮助,请告诉我!干杯。

    【讨论】:

    • 我从 JSON 加载了缩放级别,我正在尝试在 svg 加载时重新创建缩放级别。你能发布你的完整解决方案吗? :)
    • 如果该链接仍然有效,那就太好了......感谢上帝the Wayback Archive
    • 更新我的原始答案以引用存档链接。谢谢!
    • 在我的情况下是 zoomWidthzoomHeight 其中“offsetLeft”和“offsetTop”
    【解决方案4】:

    适用于 d3.js v4

    这类似于davcs86's answer,但它重用了初始变换并实现了缩放功能。

    // Initial transform to apply
    var transform = d3.zoomIdentity.translate(200, 0).scale(1);
    var zoom = d3.zoom().on("zoom", handleZoom);
    
    var svg = d3.select("body")
      .append('svg')
      .attr('width', 800)
      .attr('height', 300)
      .style("background", "red")
      .call(zoom)                       // Adds zoom functionality
      .call(zoom.transform, transform); // Calls/inits handleZoom
    
    var zoomable = svg
      .append("g")
      .attr("class", "zoomable")
      .attr("transform", transform);    // Applies initial transform
    
    var circles = zoomable.append('circle')
      .attr("id", "circles")
      .attr("cx", 100)
      .attr("cy", 100)
      .attr('r', 20);
    
    function handleZoom(){
      if (zoomable) {
        zoomable.attr("transform", d3.event.transform);
      }
    };
    

    查看实际操作:jsbin link

    【讨论】:

    • 感谢handleZoom中的if条件
    【解决方案5】:

    我使用 d3 和 react 并且对初始缩放不起作用感到非常沮丧。

    我在这里尝试了解决方案,但都没有奏效,取而代之的是使用初始比例因子和位置,然后根据这些比例因子和位置更新缩放功能

    const initialScale = 3;
    const initialTranslate = [
      width * (1 - initialScale) / 2,
      height * (1 - initialScale) / 2,
    ];
    
    const container = svg
      .append('g')
      .attr(
        'transform',
        `translate(${initialTranslate[0]}, ${initialTranslate[1]})scale(${initialScale})`
      );
    

    缩放功能看起来像这样

    svg.call(
      zoom().on('zoom', () => {
        const transformation = getEvent().transform;
        let {x, y, k} = transformation;
        x += initialTranslate[0];
        y += initialTranslate[1];
        k *= initialScale;
    
        container.attr('transform', `translate(${x}, ${y})scale(${k})`);
      })
    );
    

    如果您注意到 getEvent() 是一个函数,那是因为从 d3-selection 导入事件在我的情况下不起作用。所以我不得不这样做

    const getEvent = () => require('d3-selection').event;
    

    【讨论】:

    • 在 d3 版本 5 中是:d3.event.transform
    【解决方案6】:

    D3JS 6 答案

    假设您希望初始位置和比例分别为xyscale

    const zoom = d3.zoom();
    
    const svg = d3.select("#containerId")
        .append("svg")
        .attr("width", width)
        .attr("height", height)
        .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(scale)
        .call(zoom.on('zoom', (event) => {
            svg.attr('transform', event.transform);
         }))
        .append("g")
        .attr('transform', `translate(${x}, ${y})scale(${k})`);
    

    .call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(scale) 确保在触发缩放事件时,event.transform 变量会考虑平移和缩放。紧随其后的行处理缩放,而最后一行用于在“启动”时应用平移和缩放一次。

    【讨论】:

      猜你喜欢
      • 2015-06-21
      • 2023-04-06
      • 2018-07-05
      • 1970-01-01
      • 2023-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      相关资源
      最近更新 更多