【问题标题】:Disable D3 zoom on circle PNG background在圆形PNG背景上禁用D3缩放
【发布时间】:2018-02-22 02:26:44
【问题描述】:

我正在尝试禁用特定元素的 D3 缩放。这个元素恰好是圆形的 PNG 背景。

现在这不起作用。我试图在缩放中偏移比例参数,但背景 PNG 仍然随着圆圈“增长”。这是我的jsfiddle

这是我尝试偏移缩放的方式:

d3.selectAll("#grump_avatar").attr("transform", "scale(" + 1/d3.event.scale + ")");

我知道关于 SO 有类似的问题,但请注意,到目前为止,没有一个问题得到令人满意的答复。希望这里好运。

【问题讨论】:

  • 您不想缩放哪个元素? d3.selectAll("#grump_avatar"),您没有任何 id 为 grump_avatar 的元素。
  • 共有三个:#grump_avatar1#grump_avatar2#grump_avatar3。这些是用作每个圆圈后面背景的 PNG 图像。该代码不适用于其中任何一个。

标签: javascript css d3.js svg


【解决方案1】:

这段代码有很多问题:

  1. 按 id 匹配是精确匹配。
  2. 您的ids 位于def 属性上,这不是对象,您不想缩放(那些是圆圈)。
  3. 要匹配多个对象,您应该在圆圈上使用class
  4. 您将缩放直接应用于svg,您应该将所有内容包装在g 中。 SVG 处理事件,g 是可缩放的“画布”。
  5. 正确应用缩放后,您将失去圆圈位置,因为您覆盖了 transform 而没有重新应用 translate
  6. 您没有使用d3 数据绑定,因此您无法正确持久化数据。

记住所有这些,这是我将如何重构您的代码:

var config = {
  "avatar_size": 100
}

var body = d3.select("body");

var svg = body.append("svg")
  .attr("width", 500)
  .attr("height", 500);

var g = svg.append("g");

var defs = svg.append('svg:defs');

data = [{
  posx: 100,
  posy: 100,
  img: "https://cdn0.iconfinder.com/data/icons/flat-round-system/512/android-128.png",

}, {
  posx: 200,
  posy: 200,

  img: "https://cdn1.iconfinder.com/data/icons/social-media-set/24/Reverbnation-128.png"
}, {
  posx: 300,
  posy: 300,

  img: "https://cdn1.iconfinder.com/data/icons/user-pictures/100/male3-128.png"
}];

defs.selectAll("pattern")
  .data(data)
  .enter()
  .append("pattern")
  .attr("id", (d, i) => "grump_avatar" + i)
  .attr("width", config.avatar_size)
  .attr("height", config.avatar_size)
  .attr("patternUnits", "userSpaceOnUse")
  .append("svg:image")
  .attr("xlink:href", (d) => d.img)
  .attr("width", config.avatar_size)
  .attr("height", config.avatar_size)
  .attr("x", 0)
  .attr("y", 0);

g.selectAll(".grump_avatar")
  .data(data)
  .enter()
  .append("circle")
  .attr("class", "grump_avatar")
  .attr("transform", (d) => "translate(" + d.posx + "," + d.posy + ")")
  .attr("cx", config.avatar_size / 2)
  .attr("cy", config.avatar_size / 2)
  .attr("r", config.avatar_size / 2)
  .style("fill", "white")
  .style("fill", (d, i) => "url(#grump_avatar" + i + ")");

var zoom = d3.behavior.zoom()
  .on("zoom", function() {

    g.attr('transform', 'translate(' + d3.event.translate + ') scale(' + d3.event.scale + ')');

    d3.selectAll(".grump_avatar").attr("transform", (d) => {
      return "scale(" + 1 / d3.event.scale + ")" + "translate(" + (d.posx - d3.event.translate[0]) + "," + (d.posy - d3.event.translate[1]) + ")";
    });
  });
svg.call(zoom);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

编辑基于 cmets:

要缩放与缩放相反的圆圈并定位它们,关键是:

d3.selectAll("circle")
  .attr("transform", function(d){
    return 'scale(' + 1 / d3.event.scale + ')'; // inverse of scale for size 
  })
  .attr("cx", function(d){
    return d.x * d3.event.scale; // change position based on scale, d.x is the original unscaled position
  })
  .attr("cy", function(d){
    return d.y * d3.event.scale;
  });

【讨论】:

  • 马克,非常感谢你,我正在处理你的代码。只是一个简单的问题:我如何使用其父圆的坐标来翻译“脾气暴躁的头像”,而不是数据数组给出的绝对位置?
  • @Noobster,我不明白这个问题。
  • 现在您正在作为 d.posx 和 d.posy 的函数对 .grump_avatar 执行翻译。你可以通过使用你附加的圆圈的 cx 和 cy 来达到同样的效果吗?你会怎么做?我问是因为圆圈的位置可能会改变。
  • 马克,我创建了另一个 jsFiddle,这一次应该更好地展示我遇到的问题。我想我什至不需要解释问题是什么,当你尝试放大地图时你会直接看到它:) jsfiddle.net/Guill84/Lo2mjhjq/3
  • @Noobster,我明白你现在想要什么。看看at this
猜你喜欢
  • 1970-01-01
  • 2012-07-14
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 2014-08-26
相关资源
最近更新 更多