2016-08-26 20 views
0

疑問に思うのは、グラフ上の領域を拡大するための解決策が誰にもありません。私が言いたいのは、キャンバス上のあるポイントにマウスを置いて、押したままマウスを別の場所に移動し、マウスを上に移動してそのブロックをズームしたいということです。 x軸はスケールし、yはスケールしません。HTMLキャンバスグラフ上の領域にズーム

これはまさに私が何をしたいです -

http://canvasjs.com/docs/charts/basics-of-creating-html5-chart/zooming-panning/は、今私は、ズームインすることができましたが、私のグラフは、ズーム後の混乱です。ラインとポイントはすべて伸び、ねじれなど、私はスケールを使って調整しようとしました。

これまで私が行ってきたことです。

let y = heightOfCanvas/2, 

    // Get the region in pixels to zoom to. If canvas width 
    // is 500, this is lets say 100px to 400px. 
    regionToZoom = toX - fromX, 

    // Subtract from actual width, so we get what will be scaled 
    // out. 
    difference = widthOfCanvas - regionToZoom, 

    // Scale = fullWidth/partWidth 
    scale = widthOfCanvas/difference, 

    // This is how I worked out the value to translate back, 
    // so that it lines up right 
    translateBack = widthOfCanvas * scale 



    ctx.translate(from, y); 

    ctx.scale(scale, 1); 

    from = from * translateBack; 

    ctx.translate(-from, -y); 

    // REDRAW GRAPH AFTER 

このようにズームしても問題はありませんが、私が言ったように、それは後になります。

上記の例のように、誰かが過去に似たようなことをしたことがあれば、私は助けに感謝します。

ショーン。

+0

私はよく分かりませんが、これはあなたを助けるかもしれません。 https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save –

答えて

1

ここでは、グラフのサブセット

// canvas vars 
 
var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
ctx.font='14px arial'; 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 
function reOffset(){ 
 
    var BB=canvas.getBoundingClientRect(); 
 
    offsetX=BB.left; 
 
    offsetY=BB.top;   
 
} 
 
var offsetX,offsetY; 
 
reOffset(); 
 
window.onscroll=function(e){ reOffset(); } 
 
window.onresize=function(e){ reOffset(); } 
 

 
var isDrilled=false; 
 
var isDown=false; 
 
var startX,startY; 
 

 
// graph vars 
 
var axisY=ch/3; 
 
var points=[]; 
 

 
// DEMO: add random data points 
 
var demoPointCount=50; 
 
for(var i=0;i<demoPointCount;i++){ 
 
    points.push({y:Math.random()*150-75}); 
 
} 
 

 
// draw the full data graph 
 
draw(points,axisY); 
 

 
// listen to mouse events 
 
window.onmousedown=(function(e){handleMouseDown(e);}); 
 
window.onmousemove=(function(e){handleMouseMove(e);}); 
 
window.onmouseup=(function(e){handleMouseUpOut(e);}); 
 
window.onmouseout=(function(e){handleMouseUpOut(e);}); 
 

 

 
function draw(pts,axisY,startX,mouseX,drillStart,drillEnd){ 
 
    // redraw the given pts data 
 
    ctx.clearRect(0,0,cw,ch); 
 
    ctx.beginPath(); 
 
    ctx.moveTo(0,pts[0].y+axisY); 
 
    for(var i=0;i<pts.length;i++){ 
 
     var x=cw/(pts.length-1)*i; 
 
     ctx.lineTo(x,pts[i].y+axisY); 
 
    } 
 
    ctx.stroke(); 
 
    // used when highlighting a drilldown section of full data 
 
    if(startX && mouseX){ 
 
     ctx.globalAlpha=0.10; 
 
     ctx.fillStyle='black'; 
 
     ctx.fillRect(startX,0,mouseX-startX,ch); 
 
     ctx.globalAlpha=1.00; 
 
    }else if(drillStart && drillEnd){ 
 
     ctx.fillText('Viewing '+drillStart+' - '+drillEnd+'. Click to return to all data view.',10,20); 
 
    }else{ 
 
     ctx.fillText('Drag to select data to drill into.',10,20); 
 
    } 
 
} 
 

 
function handleMouseDown(e){ 
 
    // if displaying drilled data, return to full data 
 
    if(isDrilled){ 
 
     isDrilled=false; 
 
     draw(points,axisY); 
 
     return; 
 
    } 
 
    // tell the browser we're handling this event 
 
    e.preventDefault(); 
 
    e.stopPropagation(); 
 
    // start mouse position 
 
    startX=parseInt(e.clientX-offsetX); 
 
    startY=parseInt(e.clientY-offsetY); 
 
    // Put your mousedown stuff here 
 
    isDown=true; 
 
} 
 

 
function handleMouseUpOut(e){ 
 
    if(!isDown){return;} 
 
    // tell the browser we're handling this event 
 
    e.preventDefault(); 
 
    e.stopPropagation(); 
 
    // mouse position 
 
    mouseX=parseInt(e.clientX-offsetX); 
 
    mouseY=parseInt(e.clientY-offsetY); 
 
    // Put your mouseup stuff here 
 
    isDown=false; 
 
    isDrilled=true; 
 
    // normalize 
 
    if(mouseX<startX){ var t=startX; startX=mouseX; mouseX=t; } 
 
    // fetch highlighted start & end data points 
 
    drillStart=parseInt(startX/cw*points.length); 
 
    drillEnd=parseInt(mouseX/cw*points.length); 
 
    var subset=points.slice(drillStart,drillEnd+1); 
 
    // draw the data subset 
 
    draw(subset,axisY,null,null,drillStart,drillEnd); 
 
} 
 

 
function handleMouseMove(e){ 
 
    if(!isDown){return;} 
 
    // tell the browser we're handling this event 
 
    e.preventDefault(); 
 
    e.stopPropagation(); 
 
    // mouse position 
 
    mouseX=parseInt(e.clientX-offsetX); 
 
    mouseY=parseInt(e.clientY-offsetY); 
 
    // Put your mousemove stuff here 
 
    draw(points,axisY,startX,mouseX); 
 
}
body{ background-color:white; } 
 
#canvas{border:1px solid red; }
<canvas id="canvas" width=512 height=512></canvas>

[前の時代遅れの答え] &ディスプレイを選択する方法を示す簡単な例です

ここまでの方法です変換を覚えていることを大騒ぎすることなくズームする

これはすばやく考えられているので、微妙な調整が必要な場合があります。

  1. コピー第二メモリ内キャンバス上に描画することにより、グラフ:

    var memCanvas=myCanvas.cloneNode(); 
    var memCtx=memCanvas.getContext('2d'); 
    memCtx.drawImage(myCanvas,0,0); 
    
  2. のdrawImage memCanvas表示キャンバスに:マウスダウンで

    context.drawImage(memCanvas,0,0); 
    
  3. 、グラブ選択ボックスの左上の座標です。

  4. mouseupでは、選択ボックスの右下の座標を取得します。 注:トップ>ボトムまたは左>右の場合は、トップ&ボトムまたは左&を右にフリップする必要があります。

  5. 可視キャンバスに単に選択ボックスフルフレームを描画するために必要なスケーリング係数計算:memCanvasからだけ選択ボックスを引き出し、描画するdrawImageの切り出し形式を使用

    var scale = Math.min(
        (myCanvas.width/selectionboxWidth), 
        (myCanvas.height/selectionboxHeight) 
    ); 
    
  6. をその後

    var x=sboxLeft; 
    var y=sboxTop; 
    var w=sboxRight-sboxLeft; 
    var h=sboxBottom-sboxTop; 
    sboxcontext.drawImage(
        memCanvas,   // fetch from the memCanvas 
        x,y,w,h,    // clip the selected box 
        0,0,w*scale,h*scale); // scale the selected box into the visible canvas 
    

あなただけREDRあなたをズーム解除したい:それは目に見えるキャンバスにスケール表示されているキャンバスに完全なmemCanvasを渡します(非変換する必要はありません)。結果のグラフは混乱ではありません!

context.drawImage(memCanvas,0,0); // unzoomed -- simply! 
+0

ありがとう、私はこれを今試してみるつもりです、あなたは私がどのように乗っているか知っていますか? –

+0

そうですね、これを試してみましたが問題なくOKですが、イメージ自体はスケーリングされていますが、元の線幅を維持しようとしています。また、私のグラフはインタラクティブなものでなければならないので、ユーザがライン上を飛び越えたときには少し影がついてしまいますが、描画イメージではそのように見えません。 –

+0

おっと!私があなたのタイトルの「ズーム」を見たとき、私はあなたが拡大したいと思っていました - グラフの一部を拡大してみましょう。 [OK]をクリックすると、グラフのサブセクションにドリルダウンすると**グラフを再描画する必要があります。 1.キャンバスを 'context.scale(scale、scale)'(X方向とY方向の両方に同じ倍率でスケール)でスケーリングします。2.定義しますが、ストローク/グラフを塗りつぶしません。3. ' context.scale(-scale、-scale) '、4.ストローク/塗りつぶし。その結果、グラフはスケーリングされますが、線はスケーリングされません。 – markE

関連する問題