2017-09-22 1 views
2

Je suis en train de créer une carte interactive d'une petite zone géographique en utilisant du canevas HTML. Le canevas correspondra à la largeur et à la hauteur de l'image de carte utilisée. La carte comportera quelques points, et quand on clique dessus, la toile doit se centrer sur ce point et zoomer dessus.Comment centrer et zoomer sur un point cliqué dans le canevas

Je l'ai jusqu'à présent essayé en utilisant translate le contexte de dessin, le dessin de l'image de la carte afin que le point cliqué se trouve dans le centre de la toile, puis en utilisant scale pour zoomer, comme suit:

var clickX = e.offsetX || (e.pageX - canvas.offsetLeft); 
var clickY = e.offsetY || (e.pageY - canvas.offsetTop); 

clickedPoint = { x: clickX, y: clickY }; 

ctx.translate(
    canvas.width/2 - clickedPoint.x, 
    canvas.height/2 - clickedPoint.y 
); 
ctx.scale(2, 2); 

Toutefois, lorsque je dessine à ce stade, l'image n'apparaît pas à l'endroit prévu. Je devine parce que le point traduit ne s'aligne pas après la fonction d'échelle, car la traduction se déroule correctement sans l'échelle, mais je n'arrive pas à obtenir ce fonctionnement - quelqu'un peut-il expliquer comment résoudre cela?

EDIT: par exemple lien - http://staging.clicky.co.uk/canvas/

Répondre

2

à l'échelle et zoom sur un point sur la toile, vous devez connaître le zoom/échelle actuelle et l'origine actuelle. Si vous ne suivez pas cette information, vous ne pouvez pas mettre à l'échelle correctement à un point du canevas.

Si vous avez l'échelle et d'origine de défaut est scale = 1 et origin = {x:0,y:0}

// scale is current scale 
// origin is current origin 
function scaleAt (at, amount) { // at in screen coords amount is amount to scale 
    scale *= amount; 
    origin.x = at.x - (at.x - origin.x) * amount; 
    origin.y = at.y - (at.y - origin.y) * amount; 
}; 

var scale = 1; 
const origin = {x : 0, y : 0}; 


// in mouse event 
// scale is change in scale 
scaleAt(clickedPoint,2); // scale 2 times at clickedPoint 
// then set the transform 
ctx.setTransform(scale,0,0,scale,origin.x,origin.y) 

Pour centrer un point sur une image au centre de la toile à l'aide d'une échelle fixe

// scale and origin from above code. 
// newScale is absolute scale 
function scaleMoveCenter (point, newScale) { 
    scale = newScale; 
    origin.x = canvas.width/2 - point.x * scale; 
    origin.y = canvas.height/2 - point.y * scale; 
} 
// in mouse event 
scaleMoveCenter (clickedPoint,2); 
// then set the transform 
ctx.setTransform(scale,0,0,scale,origin.x,origin.y) 

Si le canevas possède déjà un ensemble d'échelle et d'origine différent de celui par défaut, vous devez trouver le point dans ce système de coordonnées.

// 
const realPos = {}; 
realPos.x = (clickedPoint.x - origin.x)/scale; 
realPos.y = (clickedPoint.y - origin.y)/scale; 

// increase scale by 2 
scaleMoveCenter (realPos ,scale * 2); 
// then set the transform 
ctx.setTransform(scale,0,0,scale,origin.x,origin.y) 
+0

Merci, j'ai réussi à obtenir ce travail - mais je travaille maintenant sur l'animation pour zoomer et faire un panoramique sur le point cliqué. J'essaie d'obtenir les étapes entre l'origine par défaut (vraisemblablement 0, 0) et la nouvelle origine, et mettre à jour ceci avec la nouvelle échelle à chaque image de l'animation, mais je ne suis même pas proche à la minute. tous les conseils que vous pouvez donner seraient très utiles! – jtrich

+0

@jtrich Vous pouvez interpoler l'échelle et l'origine, bien que l'échelle soit un multiplicateur, les meilleurs résultats nécessiteront une interpolation non linéaire (polynomiale) pour l'origine ou l'échelle. Mais essayez l'interpolation linéaire, si la différence d'échelle est faible, alors vous pouvez être heureux avec le look. – Blindman67

+0

Excuses, n'expliquait pas trop bien - J'ai le point de zoom comme vous l'avez décrit, mais je ne sais pas vraiment où commencer/terminer l'interpolation! J'ai pensé que je pouvais aller de 0, 0 au point cliqué et tenir compte de l'échelle à chaque point, mais c'est loin. Je suis encore assez nouveau à ce sujet, donc si vous pouviez me donner les bases ici ce serait génial, merci – jtrich