2013-01-16 4 views
9

나는 웹 프로젝트에서 자바 스크립트를 통해 캔버스를 만들고 있습니다.캔버스에서 가로 스크롤. HTML5

캔버스는 xy 평면에 그래픽 표현을 가지고 있습니다.

가로 스크롤 기능을 캔버스에 추가하려고합니다.

나는 몇 가지 방법을 조사했다 : -

1) 앞으로 마우스 스크롤, 1 월의 데이터가 사라질 때 캔버스에 데이터를 12 개월 가치가 무승부를, 그리고 마지막에 새로운 달의 데이터가 추가되고, 새로운 캔버스가 그려집니다.

단점 : - 마우스를 스크롤 할 때마다 타임 라인을 따라 이동합니다 - 새로운 SQL 쿼리를 만들어야하므로 웹 응용 프로그램이 매우 느려집니다.

2) 어쩌면 나는 1 SQL 쿼리를 통해 캔버스에 10 년 동안 가치있는 데이터를 표시 할 수 있지만 12 개월 동안의 데이터 만 표시 할 수 있습니다. 나머지 9 년은 마스킹했다. 이제 클라이언트가 스크롤 할 때 스크롤 이벤트를 캡처하고 캔버스의 해당 부분으로 이동합니다. 이것이 가능한가? 그렇다면 어떻게?

누구든지 조언 할 수 있습니까?

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

데이터의 가치는 12 개월 캔버스의 나의 현재 표현은 =

하면 스크롤에보다 구체적으로, 나는 다음과 같은 위젯과 같은 느낌 등을하고 싶습니다 내 클라이언트 측 스크롤 액션 : -

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

+1

SVG는 일반적으로 단지 말, 플로팅 데이터에 대한보다 적절한 도구로 간주됩니다. – Shmiddty

+0

하지만 원하는 것은'context.translate (-x, 0)'를 사용하여 효과를 시뮬레이트하는 것입니다. 이렇게하면 데이터 요소의 x 좌표를 변경할 필요가 없습니다. – Shmiddty

답변

12

는 여기 아주 기본적인 구현 : 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(); 
    } 
} 

그리드를 만들려면, 당신은 이런 식으로 뭔가를 할 수 :

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

+0

마침내 !! – Philo

+0

이 접근 방식을 사용하면 새로운 문제가 y 축의 정적 레이블에 나타납니다. - http://jsfiddle.net/WNpKE/10/ – Philo

+0

다른 레이어 (다른 캔버스 또는 일반 DOM 요소)에 배치하는 것이 좋습니다. – Shmiddty

3

@Shmiddty의 답변에서 모든 마우스 이동 이벤트를 다시 그리지 않으려면 전체 캔버스 크기를 그릴 수 있으며 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);