Frage Horizontales Scrollen auf Canvas. HTML5


Ich erstelle eine Leinwand über Javascript in einem Webprojekt.

Die Zeichenfläche hat grafische Darstellungen auf der x-y-Ebene.

Ich versuche, die horizontale Scrollfunktion der Leinwand hinzuzufügen.

Ich habe ein paar Methoden untersucht:

1) zeichne Daten von 12 Monaten auf die Leinwand, wenn die Maus vorwärts scrollt, die Daten des ersten Monats verschwinden und am Ende neue Monatsdaten hinzugefügt werden, wird eine neue Leinwand gezeichnet.

Con: - Jedes Mal, wenn die Maus scrollt, um durch die Timeline zu schwenken, muss eine neue SQL-Abfrage erstellt werden, die meine Webanwendung sehr langsam macht.

2) vielleicht kann ich sagen, dass 10 Jahre Daten auf der Leinwand über 1 SQL-Abfrage zeichnen, aber nur 12 Monate der Daten zeigen. maskiert den Rest der 9 Jahre. Jetzt, wenn der Client scrollt, nehme ich das Scroll-Ereignis auf und bewege mich zum entsprechenden Teil des Canvas. Ist das möglich? Wenn ja, wie?

Kann jemand beraten?

My current representation of the canvas = with only 12 months worth of data

Meine aktuelle Darstellung der Leinwand = mit nur 12 Monaten Daten

Um genauer auf das Scrollen einzugehen, möchte ich ein Gefühl wie das folgende Widget für meine clientseitige Scroll-Aktion haben:

http://www.simile-widgets.org/timeline/


9
2018-01-16 22:04


Ursprung


Antworten:


Hier ist eine ziemlich grundlegende Implementierung: http://jsfiddle.net/CQPeU/

var can = document.getElementById("can"),
    ctx = can.getContext('2d'),
    dragging = false,
    lastX = 0,
    translated = 0;

// these two lines will make the y-axis grow upwards. 
ctx.scale(1,-1);  
ctx.translate(0, -400);

can.onmousedown = function(e){
  var evt = e || event;
  dragging = true;
  lastX = evt.offsetX;
}

window.onmousemove = function(e){
  var evt = e || event;
  if (dragging){
    var delta = evt.offsetX - lastX;
    translated += delta;
    ctx.translate(delta, 0);  // translate the context.
    lastX = evt.offsetX;
    draw();  // redraw
  }
}

window.onmouseup = function(){
  dragging = false;
}


function draw() {
  ctx.clearRect(-translated, 0, 600, 400); // this is why we need to keep track of how much we've translated
  for (var i = 0; i < plot.length; i++) {
    ctx.beginPath();
    ctx.arc(plot[i].x, plot[i].y, 5, 0, 2 * Math.PI); // note we don't have to futz with the x/y values, and can use them directly. 
    ctx.fill();
  }
}

Um ein Raster zu erstellen, könnten Sie Folgendes tun:

var grid = (function(dX, dY){
  var can = document.createElement("canvas"),
      ctx = can.getContext('2d');
  can.width = dX;
  can.height = dY;
  // fill canvas color
  ctx.fillStyle = 'black';
  ctx.fillRect(0, 0, dX, dY);

  // x axis
  ctx.strokeStyle = 'orange';
  ctx.moveTo(.5, 0.5);
  ctx.lineTo(dX + .5, 0.5);
  ctx.stroke();

  // y axis
  ctx.moveTo(.5, .5);
  ctx.lineTo(.5, dY + .5);
  ctx.stroke();

  return ctx.createPattern(can, 'repeat');
})(100, 50);

Welches würde so verwendet werden:

function draw() {
  ctx.clearRect(-translated, 0, 600, 400);
  ctx.rect(-translated, 0, 600, 400);
  ctx.fillStyle = grid;
  ctx.fill();
  ctx.fillStyle = "#fff";
  for (var i = 0; i < plot.length; i++) {
    ctx.beginPath();
    ctx.arc(plot[i].x, plot[i].y, 5, 0, 2 * Math.PI);
    ctx.fill();
  }
}

Aktualisierte Demo: http://jsfiddle.net/CQPeU/2/


12
2018-01-16 23:07



Um das erneute Zeichnen bei jedem Mouse Move-Ereignis in der Antwort von @Smiddty zu vermeiden, können Sie die gesamte Zeichenfläche übergroß zeichnen und dann die CSS-Randeigenschaft ändern. Dies ist ein wesentlicher Leistungsgewinn, wenn der Inhalt des Canvas komplexer wird.

Hier ist eine Demo: https://jsfiddle.net/ax7n8944/

HTML:

<div id="canvasdiv" style="width: 500px; height: 250px; overflow: hidden">
    <canvas id="canvas" width="10000px" height="250px"></canvas>
</div>

JS:

var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var dragging = false;
var lastX;
var marginLeft = 0;

for (var i = 0; i < 1000; i++) {
    context.beginPath();
    context.arc(Math.random() * 10000, Math.random() * 250, 20.0, 0, 2 * Math.PI, false);
    context.stroke();
} 

canvas.addEventListener('mousedown', function(e) {
    var evt = e || event;
    dragging = true;
    lastX = evt.clientX;
    e.preventDefault();
}, false);

window.addEventListener('mousemove', function(e) {
    var evt = e || event;
    if (dragging) {
        var delta = evt.clientX - lastX;
        lastX = evt.clientX;
        marginLeft += delta;
        canvas.style.marginLeft = marginLeft + "px";
    }
    e.preventDefault();
}, false);

window.addEventListener('mouseup', function() {
    dragging = false;
}, false);

3
2018-04-09 00:32



Es ist besser, Phaser Framework mit dem folgenden Plugin zu verwenden http://jdnichollsc.github.io/Phaser-Kinetic-Scrolling-Plugin/


-1
2017-07-12 19:41