2013-01-16 27 views
9

私はウェブプロジェクトでjavascriptを使用してキャンバスを作成しています。キャンバス上の水平スクロール。 HTML5

キャンバスには、xy平面上に図形表現があります。

キャンバスに水平スクロール機能を追加しようとしています。

私はいくつかの方法論について検討している: -

1)前方マウススクロール、第一の月のデータが消えたときに、キャンバス上のデータの12ヶ月の価値描きをし、最後に新しいヶ月のデータが追加され、新しいキャンバスが描画されます。

欠点: - マウスがスクロールしてタイムラインをスクロールするたびに、新しいSQLクエリを作成する必要があり、Webアプリケーションが非常に遅くなります。

2)おそらく、1 SQLクエリでキャンバス上に10年分のデータを描くことができますが、そのデータは12ヶ月分しか表示できません。 9年間の残りの部分を隠す。クライアントがスクロールすると、スクロールイベントをキャプチャして、キャンバスの適切な部分に移動します。これは可能ですか?もしそうなら、どのように?

誰も助言できますか?キャンバスの私の現在の表現は=スクロールでより具体的には、データ

の価値はわずか12ヶ月で、私は、次のウィジェットなどの感覚を持っていると思い

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

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

+1

SVGは、一般的にだけ言って、プロットデータのためのより適切なツールと考えられています。 – Shmiddty

+0

しかし、あなたがしたいのは 'context.translate(-x、0)'を使ってエフェクトをシミュレートすることです。この方法では、データポイントのx座標を変更する必要はありません。 – Shmiddty

答えて

12

ここだ - :私のクライアントサイドスクロールアクションのためにかなり基本的な実装:

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

更新デモ:http://jsfiddle.net/CQPeU/2/次のように使用される

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

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

グリッドを作成するには、このような何かを行うことができます

+0

ようやく! – Philo

+0

このアプローチでは、y軸上の静的ラベルに新しい問題が生じます。 など: - http://jsfiddle.net/WNpKE/10/ – Philo

+0

別のレイヤー(別のキャンバス、または通常のDOM要素)に配置することをおすすめします。 – Shmiddty

3

@Shmiddtyからの回答でMouse Moveイベントが再描画されないようにするには、キャンバス全体を描画してから、CSSマージンプロパティを変更します。これは、キャンバスのコンテンツがより複雑になった場合に、大幅なパフォーマンスの向上につながります。ここで

はデモです: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);