javascript - d3 : canvas zooming with multiple images

标签 javascript d3.js

我使用 d3 最终创建一个具有时间序列域的面积图。除了图表之外,我还想添加一系列与日期对齐的图像。图像太宽,无法全宽显示并与 x 轴对齐,因此我正在裁剪它们。我希望在放大时剪裁能够扩大。我尝试使用 svg 图像元素进行此操作,但缩放速度太慢。所以现在我正在尝试用 Canvas 。但我陷入困境,因为我不知道如何在不重新加载多个图像的情况下重绘它们。这是我的代码:

  var imageWidth = 427,
  imageHeight = 240;

  var imageDirectory = "data/solarImages/solarImage",
    imageExtension = "jpg";

  var parseDate = d3.timeParse("%Y/%m/%d %H:%M");

  var canvas = d3.select('canvas');
  var context = canvas.node().getContext("2d");
  var width = canvas.property("width");
  var height = canvas.property("height");

  // svg = ...

  var x =
    d3.scaleTime()
      .range([0, width]);

  var y =
    d3.scaleLinear()
      .range([height, 0]);

  // data
  d3.csv("data/kW_test.csv", type).then(function(data) {
    var dataLength = data.length,
    clipWidth = width/dataLength,
    sx = (imageWidth - clipWidth)/2,
    zoomLimit = imageWidth/clipWidth;

    x.domain(d3.extent(data, function(d) { return d.date; }));

    y.domain([0, height]);

    canvas
      .call(d3.zoom().scaleExtent([1, zoomLimit]).on("zoom", zoomed));

    // loading and drawing the clipped images
    data.forEach(function(o){
      d3.image(o.image).then(function(img) {
        context.drawImage(img, sx, 0, clipWidth, imageHeight, x(o.date) - clipWidth / 2, 0, clipWidth, imageHeight);
      });
    });

    function zoomCanvas() {
      var xdom = x.domain();
      var zoomedDataArray = data.filter(function(d) {
        return d.date >= xdom[0] && d.date <= xdom[1];
      });
      dataLength = zoomedDataArray.length;
      context.clearRect(0, 0, width, height);
      clipWidth = width/dataLength;
      sx = (imageWidth - clipWidth)/2;

      // how do I access the images in the zoomed domain??
      context.drawImage(img, sx, 0, clipWidth, imageHeight, x(o.date) - clipWidth / 2, 0, clipWidth, imageHeight);
    }

    function zoomed() {
      zoomCanvas();
    }
  });

  //helper functions
  function splitDateString(dateString) {
    var stringArray = dateString.split(/\/|:|\s/);
    stringArray[0] = stringArray[0].substring(2);
    return stringArray;
  }

  function type(d, _, columns) {
    var dateArray = splitDateString(d.date);
    d.image = `${imageDirectory}${dateArray[1]}_${dateArray[2]}_${dateArray[0]}_${dateArray[3]}.${imageExtension}`;
    d.date = parseDate(d.date);
    for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
    return d;
  }

最佳答案

使用 map 怎么样?

const imageCache = new Map();
...

    d3.image(o.image).then(function(img) {
      imageCache.set(o.image, img);
...

  function zoomCanvas() {
...
    zoomedDataArray.forEach(o => {
      const img = imageCache.get(o.image);
      context.drawImage(img, sx, 0, clipWidth, imageHeight,
         ...
     })
...

关于javascript - d3 : canvas zooming with multiple images,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48901228/

相关文章:

javascript - 如何从 angularJS 模板调用 encodeURIComponent?

javascript - 如何使行悬停覆盖数据表中的选择?

javascript - Google Analytics 如何检测 IP 地址?

javascript - 类型的参数不可分配给字符串

javascript - D3 v4 同时移动圆圈和文本

javascript - 在 d3.scaleTime() 中获取恒定的刻度间隔值

php - 从 JavaScript 访问 PHP 数组

javascript - 两个 'calls' 到 d3 中的拖动事件

javascript - D3.js 的鼠标悬停事件在 Leaflet 中不起作用

javascript - 根据值隐藏和显示