SVG 路径超出 d3 画笔上的图表区域

2024-04-22

当我尝试刷动和缩放折线图的一部分时,所选区域的某些部分会呈现在图表之外。

代码和行为再现可以在以下位置找到这个jsbin https://jsbin.com/jamojonaqu/edit?js,output.

单击并拖动以选择一部分并放大,双击以缩小。

var svg = d3
  .select('body')
  .append('svg')
  .attr('class', 'chart')
  .attr('width', 960)
  .attr('height', 500);
var margin = {
  top: 40,
  right: 40,
  bottom: 40,
  left: 40
};
var width = +svg.attr('width') - margin.left - margin.right;
var height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg
  .append('g')
  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var timeParser = d3.timeParse('%Y-%m-%d');
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var brush = d3.brush().on('end', brushended);
var idleTimeout;
var idleDelay = 350;
var x0;
var y0;
var xAxis;
var yAxis;
var line = d3
  .line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.price);
  })
  .curve(d3.curveNatural);
var start = new Date();
var end = new Date(start.toDateString());
start.setFullYear(end.getFullYear() - 1);
var startStr = start.toISOString().slice(0, 10);
var endStr = end.toISOString().slice(0, 10);
var url = "https://api.coindesk.com/v1/bpi/historical/close.json?start=" + startStr + "&end=" + endStr;
d3.json(url, function(error, response) {
  var data = Object.keys(response.bpi).map(function(date) {
    return {
      date: timeParser(date),
      price: response.bpi[date]
    };
  });
  x0 = d3.extent(data, function(d) {
    return d.date;
  });
  y0 = d3.extent(data, function(d) {
    return d.price;
  });
  x.domain(x0);
  y.domain(y0);
  xAxis = d3.axisBottom(x);
  yAxis = d3.axisLeft(y);
  g
    .append('g')
    .attr('class', 'axis axis--x')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxis);
  g
    .append('g')
    .attr('class', 'axis axis--y')
    .call(yAxis);
  g
    .append('path')
    .attr('class', 'line')
    .datum(data)
    .attr('fill', 'none')
    .attr('stroke', 'steelblue')
    .attr('d', line);
  svg
    .append('g')
    .attr('class', 'brush')
    .call(brush);
});

function brushended() {
  var s = d3.event.selection;
  if (!s) {
    if (!idleTimeout) {
      return (idleTimeout = setTimeout(idled, idleDelay));
    }
    x.domain(x0);
    y.domain(y0);
  } else {
    x.domain([s[0][0] - 40, s[1][0] - 40].map(x.invert, x));
    y.domain([s[1][1] - 40, s[0][1] - 40].map(y.invert, y));
    svg.select('.brush').call(brush.move, null);
  }
  zoom();
}

function idled() {
  idleTimeout = null;
}

function zoom() {
  var t = svg.transition().duration(750);
  svg
    .select('.axis--x')
    .transition(t)
    .call(xAxis);
  svg
    .select('.axis--y')
    .transition(t)
    .call(yAxis);
  svg
    .select('.line')
    .transition(t)
    .attr('d', line);
}
.chart {
  border: 1px solid #bdbdbd;
  box-sizing: border-box;
}
<script src="https://unpkg.com/[email protected] /cdn-cgi/l/email-protection/build/d3.min.js"></script>

这是预期的行为。处理这个问题最常见的方法是使用<clipPath> https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath.

例如,在你的情况下:

var clipPath = g.append("defs")
    .append("clipPath")
    .attr("id", "clip")
    .append("rect")
    .attr("width", width)
    .attr("height", height);

然后,在你的路径中:

g.append('path')
    //etc...
    .attr("clip-path", "url(#clip)");

这是更新后的 JSBin:https://jsbin.com/tatuhipevi/1/edit?js,输出 https://jsbin.com/tatuhipevi/1/edit?js,output

这里是更新后的 S.O.片段:

var svg = d3
  .select('body')
  .append('svg')
  .attr('class', 'chart')
  .attr('width', 960)
  .attr('height', 500);
var margin = {
  top: 40,
  right: 40,
  bottom: 40,
  left: 40
};
var width = +svg.attr('width') - margin.left - margin.right;
var height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg
  .append('g')
  .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var clipPath = g.append("defs")
  .append("clipPath")
  .attr("id", "clip")
  .append("rect")
  .attr("width", width)
  .attr("height", height);
var timeParser = d3.timeParse('%Y-%m-%d');
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var brush = d3.brush().on('end', brushended);
var idleTimeout;
var idleDelay = 350;
var x0;
var y0;
var xAxis;
var yAxis;
var line = d3
  .line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.price);
  })
  .curve(d3.curveNatural);
var start = new Date();
var end = new Date(start.toDateString());
start.setFullYear(end.getFullYear() - 1);
var startStr = start.toISOString().slice(0, 10);
var endStr = end.toISOString().slice(0, 10);
var url = "https://api.coindesk.com/v1/bpi/historical/close.json?start=" + startStr + "&end=" + endStr;
d3.json(url, function(error, response) {
  var data = Object.keys(response.bpi).map(function(date) {
    return {
      date: timeParser(date),
      price: response.bpi[date]
    };
  });
  x0 = d3.extent(data, function(d) {
    return d.date;
  });
  y0 = d3.extent(data, function(d) {
    return d.price;
  });
  x.domain(x0);
  y.domain(y0);
  xAxis = d3.axisBottom(x);
  yAxis = d3.axisLeft(y);
  g
    .append('g')
    .attr('class', 'axis axis--x')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxis);
  g
    .append('g')
    .attr('class', 'axis axis--y')
    .call(yAxis);
  g
    .append('path')
    .attr('class', 'line')
    .datum(data)
    .attr('fill', 'none')
    .attr('stroke', 'steelblue')
    .attr('d', line)
    .attr("clip-path", "url(#clip)");
  svg
    .append('g')
    .attr('class', 'brush')
    .call(brush);
});

function brushended() {
  var s = d3.event.selection;
  if (!s) {
    if (!idleTimeout) {
      return (idleTimeout = setTimeout(idled, idleDelay));
    }
    x.domain(x0);
    y.domain(y0);
  } else {
    x.domain([s[0][0] - 40, s[1][0] - 40].map(x.invert, x));
    y.domain([s[1][1] - 40, s[0][1] - 40].map(y.invert, y));
    svg.select('.brush').call(brush.move, null);
  }
  zoom();
}

function idled() {
  idleTimeout = null;
}

function zoom() {
  var t = svg.transition().duration(750);
  svg
    .select('.axis--x')
    .transition(t)
    .call(xAxis);
  svg
    .select('.axis--y')
    .transition(t)
    .call(yAxis);
  svg
    .select('.line')
    .transition(t)
    .attr('d', line);
}
.chart {
  border: 1px solid #bdbdbd;
  box-sizing: border-box;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

另外,使用<clipPath>也在轴上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SVG 路径超出 d3 画笔上的图表区域 的相关文章

  • 设置 D3 力定向图

    致尊敬的读者 我对 javascript 相当陌生 我也遇到过这个问题 我正在尝试实现这个力导向图的修改版本 http mbostock github com d3 ex force html http mbostock github co
  • D3.以编程方式缩放后使用鼠标滚轮时缩放会跳转

    当我通过单击鼠标缩放到特定位置然后尝试平移或使用鼠标滚轮时 缩放行为会跳跃 看来我的缩放级别正在恢复 就像单击鼠标之前一样 这是我的事件处理程序 function click d var x y k if d centered d var
  • 调整发散堆积条形图以使用通用更新模式

    我一直在使用可用的堆积条形图示例here https bl ocks org mbostock b5935342c6d21928111928401e2c8608使用以下代码 var data month Q1 2016 apples 384
  • 如何在 d3.js 中的节点上制作双击事件?

    我想在节点上进行双击事件 所以我尝试了 on dbclick function d return http google com and bind dbclick function d alert hello 但一切都失败了 谁能帮我 完整
  • 移动浏览器上带有阴影模糊的 SVG

    我正在努力在尽可能多的平台上制作带有阴影的 SVG 图标 我为此使用以下简单的 CSS test width 14px height 14px background image url images test svg background
  • 在 Android 中使用矢量图像在真实设备上出现问题。 SVG-android

    I use svg android jar from https github com pents90 svg android其工作正常 但仅在 Eclipse 中的模拟器设备上 啊啊啊啊 在真实设备上它只是空的imageView在屏幕上
  • 学习 SVG 的书籍/教程 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Android和播放SVG动画

    我正在编写一个 Android 应用程序 我想播放一个简单的 SVG 动画 我知道 Android 不提供 SVG 支持 我在这里有什么选择 从 Android Lollipop API 级别 21 开始 可以使用动画矢量Drawable
  • 如何使用 d3.js 沿 GeoJSON 路径对对象进行动画处理?

    我正在使用 D3 js 从 GeoJSON 文件生成并渲染路径 效果很好 但现在我想沿着该路径为对象设置动画 我知道如何使用 D3 和标准 SVG 来做到这一点 创建过渡并设置其持续时间 对于过渡的每一帧 使用 Complete 查找沿路径
  • SVG 元素出现在 DOM 中但在屏幕上不可见

    我尝试使用 SVG 绘制五线谱Vexflow http www vexflow com and 拉斐尔 js http raphaeljs com当我加载页面时 SVG 元素出现在 DOM 中 但它们不会出现在屏幕上 我检查了是否有任何 C
  • d3.js - 具有树形布局,如何更改 X 轴以使用 D3 中的时间刻度?

    我有这个树布局 需要它在 X 轴上使用时间刻度来将节点固定为日期 另外 我需要保留根节点 它有一个is rootJSON 数据中的属性 在时间范围之外 Here http codepen io anon pen kIJxo是具有树布局工作的
  • crossfilter - 计算具有属性的所有记录的百分比

    这是我的问题 我正在使用 python Flask 服务器从 mongo db 获取 json 数据 并在其中指定要导入的字段 此数据采用 json 格式 并且仅像这样获取 一旦通过 graphs js 中的 crossfilter 是否可
  • Android 上的 SVG 支持

    Android 支持 SVG 吗 有什么例子吗 最完整的答案是这样的 Android 2 x 默认浏览器本身不支持 SVG Android 3 默认浏览器支持 SVG 要将 SVG 支持添加到 2 x 版本的平台 您有两个基本选择 安装功能
  • 使用velocity.js制作可拖动元素的动画

    我正在使用velocity js 为用户拖动的可拖动 SVG 元素设置动画 然而 velocity js 将先前的 mousemove 坐标排队并通过所有后续的 mousemove 坐标进行动画处理 我想要的是velocity js 不要对
  • 将 SVG 的高度设置为行高?

    我想将我的 SVG 图像作为图标包含在标题旁边 h1 img src icon sell svg class icon Verkaufen h1 字体大小为h1 is 36px和line heigt is 1 1 我使用检查器工具发现计算出
  • Snap.svg - 停止在可悬停元素的子元素上重新触发悬停事件

    对于一个项目 我使用的 SVG 形状由背景多边形和背景多边形上方的一些文本 我已将其转换为路径 组成 我正在使用 Snap svg 为我的形状设置动画 当我将鼠标悬停在多边形上时 形状应该缩放到特定尺寸 包括其中的所有内容 鼠标移开时 形状
  • 有没有办法将 SVG 字符串渲染到 Web Worker 中的 OffscreenCanvas?

    我正在开发一个网页 对 SVG 字符串数据进行一些相当繁重的处理 因为这些字符串的大小可能达到 m bs 所以我想将 SVG 的渲染 取决于浏览器 移至工作人员 以避免阻塞 UI 我的问题是 worker 中无法访问 DOM 元素 有没有办
  • Canvas drawImage 内联 svg 在 Firefox 上不起作用

    这是一个例子 它采用 svg 并将其转换为画布 http jsfiddle net Na6X5 944 http jsfiddle net Na6X5 944 var can document getElementById canvas1
  • d3js v5 + Topojson v3 关于加入 csv 和 json 的优化

    为了制作地图 我需要将一些值从 csv 导入到 json直接在代码中 为了加载 json 和 csv 文件 我使用 Promise 对象的异步操作 并使用两个循环和一个公共键在 json 文件上添加新属性 for var i 0 i lt
  • 如何将所有后代节点和链接设置为与 2 级祖先相同的颜色?

    我有一个 d3 js 树 其后代节点接收其 2 级祖先的节点颜色 这在级别 2 到级别 3 之间有效 但在级别 4 及以上级别停止工作 相关代码 var colourScale d3 scale ordinal domain MD Prof

随机推荐