d3:使用多个图像缩放画布

时间:2018-02-21 08:31:05

标签: javascript d3.js

我正在使用d3最终创建一个带有时间序列域的区域图表。随着图表,我想包括一系列与日期对齐的图像。图像太宽,无法显示全宽并与x轴对齐,因此我剪裁它们。我希望剪裁在我放大时展开。我尝试使用svg图像元素,但缩放太慢了。所以现在我用帆布尝试它。但我被卡住了,因为我不知道如何重新绘制多个图像而不重新加载它们。这是我的代码:

  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;
  }

1 个答案:

答案 0 :(得分:1)

如何使用地图?

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,
         ...
     })
...