首页 > 解决方案 > 如何使用 JavaScript 画布创建无限网格?

问题描述

如何使用 JavaScript 画布创建可缩放和可平移的无限网格?

以下是使用名为 snap.js 的库创建可拖动无限网格的代码

const paper = new Snap("#host");

const minorLineAttr = { stroke: "gray", strokeWidth: 0.5 },
      elements = [],
      dimension = 100,
      divisions = 10;

// background box
elements.push(paper.rect(0, 0, dimension, dimension).attr({
  fill: 'none',
  stroke: "gray", strokeWidth: 1
}));

// add horizontal & vertical lines
const lineCount = dimension / divisions;

for (var index=1; index < lineCount; index++) {
  const offset = lineCount*index,
        sw = minorLineAttr.strokeWidth;
  
  elements.push(paper.line(sw, offset, dimension-sw, offset).attr(minorLineAttr));
  elements.push(paper.line(offset, sw, offset, dimension-sw).attr(minorLineAttr));
}

// construct a 3x3 grid that is essentially masked to a 1x1 pattern
var gridPattern = paper.g(...elements).toPattern(0, 0, dimension, dimension);
const gridRect = paper.rect(-dimension, -dimension, 3*dimension, 3*dimension).attr({fill: gridPattern});
const grid3x3Pattern = gridRect.toPattern(0, 0, dimension, dimension);
const bgRect = paper.rect(0,0,'100%','100%').attr({fill: grid3x3Pattern});

function getElementCoords(x, y, t) {
  return {
    x : t.e + x * t.a + y * t.c,
    y: t.f + x * t.b + y * t.d
  };
}

// transform on drag
const dragStart = function () {
  console.log(this);
  const bbox = this.getBBox(),
        coords = getElementCoords(bbox.x, bbox.y, gridRect.transform().localMatrix);
  this.data("coords", coords);
};

const dragMove = function(dx, dy) {
  const coords = this.data("coords");
  gridRect.transform("t" + (coords.x + dx) % dimension + " " + (coords.y + dy) % dimension);
};

const dragStop = function() {
  this.removeData("coords");
};

bgRect.drag(dragMove, dragStart, dragStop);

paper.text(20, 50, "Drag the background").attr({
  fill: "#fff",
  fontFamily: "Verdana, Arial, Courier",
  fontSize: "24"
});

这很好用,但我想要实现的是我想使用 html5 canvas api 创建一个类似的网格。

我正在使用 Konva 创建 html 画布,因为该库具有丰富的功能。

如何使用 html5 画布或使用 konva js 实现上述无限缩放和可平移网格?

请注意,由于内容很多,我的画布溢出了屏幕。

因此,我们需要一种模拟无限网格的方法,如上图所示,它可以限制视口/容器/窗口的尺寸,并通过拖动和缩放与用户交互。

我通过创建一堆水平和垂直线尝试了自己的方式。但是画布变慢了……当我交互时……我们需要一种缓存或模拟无限网格的方法,以便提高性能。

但是当拖动它时,它不会被限制在视口/容器/窗口的宽度和高度上,如上面的 snap.svg 示例所示。

我怎样才能做到这一点?

标签: javascript

解决方案


推荐阅读