сделать холст прокручиваемым размером больше размера окна [дубликат]

Очень простой способ - установить scroll to на высоту div.

var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
3
задан Vineet 25 March 2016 в 13:07
поделиться

2 ответа

Таким образом, ваши чертежи узлов не подходят для размера холста?

Вы можете легко «сжать» свой контент, чтобы он соответствовал видимому холсту всего за 1 команду!

Команда context.scale(horizontalRescale,verticalRescale) будет сжимать каждый следующий чертеж вашим указанным горизонтальным разрешением & amp; verticalRescale проценты.

Важное примечание: Вы должны сделать horizontalRescale, verticalRescale то же значение или ваш контент будет искажен.

Приятная вещь об использовании context.scale что вам не нужно менять какой-либо код, который рисует ваши узлы ... canvas автоматически масштабирует все эти узлы для вас.

Например, этот код уменьшит ваши узлы до 80% их оригиналов size:

var downscaleFactor= 0.80;

context.scale( downscaleFactor, downscaleFactor );

Вместо того, чтобы проходить через ваши 200 + строк кода, я оставляю его вам для расчета downscaleFactor.

1
ответ дан markE 18 August 2018 в 14:19
поделиться
  • 1
    Оно работает. Thanx. Помимо опции масштабирования. Можно ли перетаскивать холст горизонтально и вертикально, чтобы пользователь мог видеть все возможные узлы, просто прокручивая или, если я нажимаю на верхний узел, все узлы, подключенные к нему, будут видны, и холст автоматически прокручивается до этой позиции – Vineet 25 March 2016 в 20:42
  • 2
    Да, автопрокрутка возможна путем перерисовки всего холста, но потянув его горизонтально и amp; вертикально до тех пор, пока не будут видны нужные вам узлы (узлы). Так же, как context.scale в моем ответе, вы можете использовать context.translate( horizontalOffset, verticalOffset), чтобы вывести нужные вам узлы. Нет никакой гарантии, что все ваши нужные узлы будут соответствовать размеру доступного холста, поэтому вам все равно придется делать context.scale. Удачи с вашим проектом! :-) – markE 25 March 2016 в 21:10

<canvas> контекст не имеет встроенного метода прокрутки.

У вас есть несколько способов обойти это ограничение.

Первый, как в @ markE, чтобы масштабировать матрицу вашего контекста, чтобы ваши рисунки соответствовали требуемому пространству. Вы также можете реорганизовать свой код, чтобы все координаты были относительно размера холста. Таким образом, вам не понадобятся полосы прокрутки, и все ваши рисунки будут просто масштабированы соответствующим образом, что является желательным поведением в большинстве распространенных случаев.


Но если вам действительно нужна функция прокрутки, вот несколько способов:


Самый простой и наиболее рекомендуемый вариант: пусть браузер обрабатывает его.

Вам нужно будет установить размер вашего холста максимально рисунков и обернуть его в другой элемент, который будет прокручиваться. Установив свойство overflow:auto css в контейнере, появятся наши полосы прокрутки, и у нас есть функция прокрутки.

В следующем примере холст имеет ширину 5000 пикселей и контейнер 200 пикселей.

var ctx = canvas.getContext('2d');
ctx.textAlign = 'center';
for (var w = 0; w < canvas.width; w += 100) {
  for (var h = 0; h < canvas.height; h += 100) {
    ctx.fillText(w + ',' + h, w, h);
  }
}
#container {
  width: 200px;
  height: 200px;
  overflow: auto;
  border: 1px solid;
}
canvas{
  display: block;
}
<div id="container">
  <canvas id="canvas" height="5000" width="5000"></canvas>
</div>

Основные преимущества:

  • легко реализованы.
  • Для этих полос прокрутки используются пользователи
  • .

Основные оговорки:

  • Вы ограничены максимальными размерами холста .
  • Если ваш холст анимирован, вы также рисуете для каждой части кадра холста, которые не видны.
  • У вас есть небольшой контроль над просмотром полос прокрутки, и вам все равно придется реализовать функцию перетаскивания для прокрутки для настольных браузеров.

Второе решение , заключается в том, чтобы реализовать эту функцию самостоятельно, используя методы преобразования холста: особенно translate , transform и setTransform .

Вот пример:

var ctx = canvas.getContext('2d');

var app = {};
// the total area of our drawings, can be very large now
app.WIDTH = 5000;
app.HEIGHT = 5000;

app.draw = function() {
  // reset everything (clears the canvas + transform + fillStyle + any other property of the context)
  canvas.width = canvas.width;

  // move our context by the inverse of our scrollbars' left and top property
  ctx.setTransform(1, 0, 0, 1, -app.scrollbars.left, -app.scrollbars.top);

  ctx.textAlign = 'center';
  // draw only the visible area
  var visibleLeft = app.scrollbars.left;
  var visibleWidth = visibleLeft + canvas.width;
  var visibleTop = app.scrollbars.top
  var visibleHeight = visibleTop + canvas.height;

  // you probably will have to make other calculations than these ones to get your drawings
  // to draw only where required
  for (var w = visibleLeft; w < visibleWidth + 50; w += 100) {
    for (var h = visibleTop; h < visibleHeight + 50; h += 100) {
      var x = Math.round((w) / 100) * 100;
      var y = Math.round((h) / 100) * 100;
      ctx.fillText(x + ',' + y, x, y);
    }
  }

  // draw our scrollbars on top if needed
  app.scrollbars.draw();
}

app.scrollbars = function() {
  var scrollbars = {};
  // initial position
  scrollbars.left = 0;
  scrollbars.top = 0;
  // a single constructor for both horizontal and vertical	
  var ScrollBar = function(vertical) {
    var that = {
      vertical: vertical
    };

    that.left = vertical ? canvas.width - 10 : 0;
    that.top = vertical ? 0 : canvas.height - 10;
    that.height = vertical ? canvas.height - 10 : 5;
    that.width = vertical ? 5 : canvas.width - 10;
    that.fill = '#dedede';

    that.cursor = {
      radius: 5,
      fill: '#bababa'
    };
    that.cursor.top = vertical ? that.cursor.radius : that.top + that.cursor.radius / 2;
    that.cursor.left = vertical ? that.left + that.cursor.radius / 2 : that.cursor.radius;

    that.draw = function() {
      if (!that.visible) {
        return;
      }
      // remember to reset the matrix
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      // you can give it any shape you like, all canvas drawings operations are possible
      ctx.fillStyle = that.fill;
      ctx.fillRect(that.left, that.top, that.width, that.height);
      ctx.beginPath();
      ctx.arc(that.cursor.left, that.cursor.top, that.cursor.radius, 0, Math.PI * 2);
      ctx.fillStyle = that.cursor.fill;
      ctx.fill();
    };
    // check if we're hovered
    that.isHover = function(x, y) {
      if (x >= that.left - that.cursor.radius && x <= that.left + that.width + that.cursor.radius &&
        y >= that.top - that.cursor.radius && y <= that.top + that.height + that.cursor.radius) {
        // we are so record the position of the mouse and set ourself as the one hovered
        scrollbars.mousePos = vertical ? y : x;
        scrollbars.hovered = that;
        that.visible = true;
        return true;
      }
      // we were visible last call and no wheel event is happening
      else if (that.visible && !scrollbars.willHide) {
        that.visible = false;
        // the app should be redrawn
        return true;
      }
    }

    return that;
  };

  scrollbars.horizontal = ScrollBar(0);
  scrollbars.vertical = ScrollBar(1);

  scrollbars.hovered = null;
  scrollbars.dragged = null;
  scrollbars.mousePos = null;
  // check both of our scrollbars
  scrollbars.isHover = function(x, y) {
    return this.horizontal.isHover(x, y) || this.vertical.isHover(x, y);
  };
  // draw both of our scrollbars
  scrollbars.draw = function() {
    this.horizontal.draw();
    this.vertical.draw();
  };
  // check if one of our scrollbars is visible
  scrollbars.visible = function() {
    return this.horizontal.visible || this.vertical.visible;
  };
  // hide it...
  scrollbars.hide = function() {
    // only if we're not using the mousewheel or dragging the cursor
    if (this.willHide || this.dragged) {
      return;
    }
    this.horizontal.visible = false;
    this.vertical.visible = false;
  };

  // get the area's coord relative to our scrollbar
  var toAreaCoord = function(pos, scrollBar) {
    var sbBase = scrollBar.vertical ? scrollBar.top : scrollBar.left;
    var sbMax = scrollBar.vertical ? scrollBar.height : scrollBar.width;
    var areaMax = scrollBar.vertical ? app.HEIGHT - canvas.height : app.WIDTH - canvas.width;

    var ratio = (pos - sbBase) / (sbMax - sbBase);

    return areaMax * ratio;
  };

  // get the scrollbar's coord relative to our total area
  var toScrollCoords = function(pos, scrollBar) {
    var sbBase = scrollBar.vertical ? scrollBar.top : scrollBar.left;
    var sbMax = scrollBar.vertical ? scrollBar.height : scrollBar.width;
    var areaMax = scrollBar.vertical ? app.HEIGHT - canvas.height : app.WIDTH - canvas.width;

    var ratio = pos / areaMax;

    return ((sbMax - sbBase) * ratio) + sbBase;
  }

  scrollbars.scroll = function() {
      // check which one of the scrollbars is active
      var vertical = this.hovered.vertical;
      // until where our cursor can go
      var maxCursorPos = this.hovered[vertical ? 'height' : 'width'];
      var pos = vertical ? 'top' : 'left';
      // check that we're not out of the bounds
      this.hovered.cursor[pos] = this.mousePos < 0 ? 0 :
        this.mousePos > maxCursorPos ? maxCursorPos : this.mousePos;

      // seems ok so tell the app we scrolled
      this[pos] = toAreaCoord(this.hovered.cursor[pos], this.hovered);
      // redraw everything
      app.draw();
    }
    // because we will hide it after a small time
  scrollbars.willHide;
  // called by the wheel event
  scrollbars.scrollBy = function(deltaX, deltaY) {
    // it's not coming from our scrollbars
    this.hovered = null;
    // we're moving horizontally
    if (deltaX) {
      var newLeft = this.left + deltaX;
      // make sure we're in the bounds
      this.left = newLeft > app.WIDTH - canvas.width ? app.WIDTH - canvas.width : newLeft < 0 ? 0 : newLeft;
      // update the horizontal cursor
      this.horizontal.cursor.left = toScrollCoords(this.left, this.horizontal);
      // show our scrollbar
      this.horizontal.visible = true;
    }
    if (deltaY) {
      var newTop = this.top + deltaY;
      this.top = newTop > app.HEIGHT - canvas.height ? app.HEIGHT - canvas.height : newTop < 0 ? 0 : newTop;
      this.vertical.cursor.top = toScrollCoords(this.top, this.vertical);
      this.vertical.visible = true;
    }
    // if we were called less than the required timeout
    clearTimeout(this.willHide);
    this.willHide = setTimeout(function() {
      scrollbars.willHide = null;
      scrollbars.hide();
      app.draw();
    }, 500);
    // redraw everything
    app.draw();
  };

  return scrollbars;
}();

var mousedown = function(e) {
  // tell the browser we handle this
  e.preventDefault();
  // we're over one the scrollbars
  if (app.scrollbars.hovered) {
    // new promotion ! it becomes the dragged one
    app.scrollbars.dragged = app.scrollbars.hovered;
    app.scrollbars.scroll();
  }
};

var mousemove = function(e) {
  // check the coordinates of our canvas in the document
  var rect = canvas.getBoundingClientRect();
  var x = e.clientX - rect.left;
  var y = e.clientY - rect.top;
  // we're dragging something
  if (app.scrollbars.dragged) {
    // update the mouse position
    app.scrollbars.mousePos = app.scrollbars.dragged.vertical ? y : x;
    app.scrollbars.scroll();
  } else if (app.scrollbars.isHover(x, y)) {
    // something has changed, redraw to show or hide the scrollbar
    app.draw();
  }
  e.preventDefault();
};
var mouseup = function() {
  // we dropped it
  app.scrollbars.dragged = null;
};

var mouseout = function() {
  // we're out
  if (app.scrollbars.visible()) {
    app.scrollbars.hide();
    app.scrollbars.dragged = false;
    app.draw();
  }
};

var mouseWheel = function(e) {
  e.preventDefault();
  app.scrollbars.scrollBy(e.deltaX, e.deltaY);
};

canvas.addEventListener('mousemove', mousemove);
canvas.addEventListener('mousedown', mousedown);
canvas.addEventListener('mouseup', mouseup);
canvas.addEventListener('mouseout', mouseout);
canvas.addEventListener('wheel', mouseWheel);

range.onchange = function() {
  app.WIDTH = app.HEIGHT = this.value;
  app.scrollbars.left = 0;
  app.scrollbars.top = 0;
  app.draw();
};

// an initial drawing
app.draw();
canvas {border: 1px solid;}
span{font-size: .8em;}
<canvas id="canvas" width="200" height="150"></canvas>
<span>
  change the total area size
  <input type="range" min="250" max="5000000" steps="250" value="5000" id="range" />
</span>

Основные преимущества:

  • нет ограничений по размеру областей рисования.
  • вы можете настроить свои полосы прокрутки по своему усмотрению.
  • вы можете управлять, когда полосы прокрутки включены или нет.
  • вы можете легко получить видимую область.

Основные предостережения:

  • немного больше кода, чем решение CSS ...
  • нет, действительно, много кода ...

Третий способ Я написал некоторое время назад для другого вопроса, воспользовавшегося возможностью рисовать другой холст с помощью ctx.drawImage() , У этого есть свои собственные предостережения и преимущества, поэтому я позволил вам выбрать тот, который вам нужен, но у этого последнего также была функция перетаскивания и слайда, которая может быть полезна.

13
ответ дан Kaiido 18 August 2018 в 14:19
поделиться
  • 1
    Если позволить браузеру работать, это сработало для меня (спасибо!), Но поскольку это встроенный элемент, холст прокручивается слишком далеко, если он не установлен для отображения: block, см. stackoverflow.com/questions/50784177/canvas-scrolls-too -far – John Leonard 11 June 2018 в 07:23
Другие вопросы по тегам:

Похожие вопросы: