Moim celem jest utworzenie wtyczki umożliwiającej powiększanie operacji na obszarze strony, podobnie jak obecnie działa Google Maps (co oznacza: przewijanie za pomocą myszy = powiększanie/zmniejszanie obszaru, klikanie & przytrzymaj & move & release = panoramowanie).CSS3 powiększanie kursora myszy
Podczas przewijania chcę wykonać operację powiększenia na środku kursora myszy.
Do tego używam transformacji macierzy CSS3 "w locie". Jedynym, ale obowiązkowym, ograniczeniem jest to, że nie mogę użyć niczego innego niż transformacja CSS3 transformata skali &, ze źródłem transformacji 0px 0px.
Przesuwanie jest poza zakresem mojego pytania, ponieważ już działa. Jeśli chodzi o powiększanie, walczę, aby dowiedzieć się, gdzie błąd jest w moim kodzie javascript.
Problem musi być gdzieś w funkcji MouseZoom.prototype.zoom, w obliczeniach tłumaczenia na osi X i osi Y.
pierwsze, tutaj jest mój kod HTML:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width = device-width, initial-scale = 1.0, user-scalable = no" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="jquery.mousewheel.min.js"></script>
<script src="StackOverflow.js"></script>
<style type="text/css" media="all">
#drawing {
position: absolute;
top: 0px;
left: 0px;
right:0;
bottom:0;
z-index: 0;
background: url(http://catmacros.files.wordpress.com/2009/09/cats_banzai.jpg) no-repeat;
background-position: 50% 50%;
}
</style>
<title>Test</title>
</head>
<body>
<div id="drawing"></div>
<script>
var renderer = new ZoomPanRenderer("drawing");
</script>
</body>
</html>
Jak widać, używam jQuery i wtyczki koła jquery mysz z Brandon Aarona, który można znaleźć tutaj: https://github.com/brandonaaron/jquery-mousewheel/
Oto zawartość pliku StackOverflow.js:
/*****************************************************
* Transformations
****************************************************/
function Transformations(translateX, translateY, scale){
this.translateX = translateX;
this.translateY = translateY;
this.scale = scale;
}
/* Getters */
Transformations.prototype.getScale = function(){ return this.scale; }
Transformations.prototype.getTranslateX = function(){ return this.translateX; }
Transformations.prototype.getTranslateY = function(){ return this.translateY; }
/*****************************************************
* Zoom Pan Renderer
****************************************************/
function ZoomPanRenderer(elementId){
this.zooming = undefined;
this.elementId = elementId;
this.current = new Transformations(0, 0, 1);
this.last = new Transformations(0, 0, 1);
new ZoomPanEventHandlers(this);
}
/* setters */
ZoomPanRenderer.prototype.setCurrentTransformations = function(t){ this.current = t; }
ZoomPanRenderer.prototype.setZooming = function(z){ this.zooming = z; }
/* getters */
ZoomPanRenderer.prototype.getCurrentTransformations = function(){ return this.current; }
ZoomPanRenderer.prototype.getZooming = function(){ return this.zooming; }
ZoomPanRenderer.prototype.getLastTransformations = function(){ return this.last; }
ZoomPanRenderer.prototype.getElementId = function(){ return this.elementId; }
/* Rendering */
ZoomPanRenderer.prototype.getTransform3d = function(t){
var transform3d = "matrix3d(";
transform3d+= t.getScale().toFixed(10) + ",0,0,0,";
transform3d+= "0," + t.getScale().toFixed(10) + ",0,0,";
transform3d+= "0,0,1,0,";
transform3d+= t.getTranslateX().toFixed(10) + "," + t.getTranslateY().toFixed(10) + ",0,1)";
return transform3d;
}
ZoomPanRenderer.prototype.getTransform2d = function(t){
var transform3d = "matrix(";
transform3d+= t.getScale().toFixed(10) + ",0,0," + t.getScale().toFixed(10) + "," + t.getTranslateX().toFixed(10) + "," + t.getTranslateY().toFixed(10) + ")";
return transform3d;
}
ZoomPanRenderer.prototype.applyTransformations = function(t){
var elem = $("#" + this.getElementId());
elem.css("transform-origin", "0px 0px");
elem.css("-ms-transform-origin", "0px 0px");
elem.css("-o-transform-origin", "0px 0px");
elem.css("-moz-transform-origin", "0px 0px");
elem.css("-webkit-transform-origin", "0px 0px");
var transform2d = this.getTransform2d(t);
elem.css("transform", transform2d);
elem.css("-ms-transform", transform2d);
elem.css("-o-transform", transform2d);
elem.css("-moz-transform", transform2d);
elem.css("-webkit-transform", this.getTransform3d(t));
}
/*****************************************************
* Event handler
****************************************************/
function ZoomPanEventHandlers(renderer){
this.renderer = renderer;
/* Disable scroll overflow - safari */
document.addEventListener('touchmove', function(e) { e.preventDefault(); }, false);
/* Disable default drag opeartions on the element (FF makes it ready for save)*/
$("#" + renderer.getElementId()).bind('dragstart', function(e) { e.preventDefault(); });
/* Add mouse wheel handler */
$("#" + renderer.getElementId()).bind("mousewheel", function(event, delta) {
if(renderer.getZooming()==undefined){
var offsetLeft = $("#" + renderer.getElementId()).offset().left;
var offsetTop = $("#" + renderer.getElementId()).offset().top;
var zooming = new MouseZoom(renderer.getCurrentTransformations(), event.pageX, event.pageY, offsetLeft, offsetTop, delta);
renderer.setZooming(zooming);
var newTransformation = zooming.zoom();
renderer.applyTransformations(newTransformation);
renderer.setCurrentTransformations(newTransformation);
renderer.setZooming(undefined);
}
return false;
});
}
/*****************************************************
* Mouse zoom
****************************************************/
function MouseZoom(t, mouseX, mouseY, offsetLeft, offsetTop, delta){
this.current = t;
this.offsetLeft = offsetLeft;
this.offsetTop = offsetTop;
this.mouseX = mouseX;
this.mouseY = mouseY;
this.delta = delta;
}
MouseZoom.prototype.zoom = function(){
var previousScale = this.current.getScale();
var newScale = previousScale + this.delta/5;
if(newScale<1){
newScale = 1;
}
var ratio = newScale/previousScale;
var imageX = this.mouseX - this.offsetLeft;
var imageY = this.mouseY - this.offsetTop;
var previousTx = - this.current.getTranslateX() * previousScale;
var previousTy = - this.current.getTranslateY() * previousScale;
var previousDx = imageX * previousScale;
var previousDy = imageY * previousScale;
var newTx = (previousTx * ratio + previousDx * (ratio - 1))/newScale;
var newTy = (previousTy * ratio + previousDy * (ratio - 1))/newScale;
return new Transformations(-newTx, -newTy, newScale);
}
Sugestie: (1) użyj jsfiddle, łatwo jest zobaczyć wynik (2) opisać "usterkę" w bardziej szczegółach. –
Po prostu wskazówka - Czy widziałeś wtyczkę o nazwie zoomooz.js, jeśli nie, może mieć wiele pinpointów do tego, co chcesz zrobić - http://janne.aukia.com/zoomooz/ –