Bir noktayı yakınlaştırma (ölçekle ve çevir kullanarak)


156

Google Haritalar'da yakınlaştırma gibi bir HTML 5 tuvalinde farenin altındaki noktayı yakınlaştırabilmek istiyorum . Bunu nasıl başarabilirim?


2
Bunu tuvalimi yakınlaştırmak için kullandım ve harika çalışıyor! Eklemem gereken tek şey, yakınlaştırma miktarının hesaplanmasını beklediğiniz gibi değil. "var zoom = 1 + tekerlek / 2;" yani bu, yakınlaştırma için 1,5 ve uzaklaştırma için 0,5 ile sonuçlanır. Yakınlaştırma için 1.5 ve yakınlaştırma için 1 / 1.5 olacak şekilde yakınlaştırma ve uzaklaştırma miktarını eşit olacak şekilde bu sürümü düzenledim. Dolayısıyla, bir kez yakınlaştırıp geri yakınlaştırırsanız yakınlaştırmadan önceki ile aynı resme sahip olursunuz.
Chris

2
Bunun Firefox'ta çalışmadığını, ancak yöntemin jQuery fare tekerleği eklentisine kolayca uygulanabileceğini unutmayın . Paylaşım için teşekkürler!
johndodo

2
var zoom = Math.pow (1.5f, tekerlek); // Yakınlaştırmayı hesaplamak için bunu kullanın. Çark = 2 ile zum yapmanın, çark = 2 ile iki zum yapmayla aynı olması avantajına sahiptir. Ayrıca, +2 ile yakınlaştırma ve +2 ile uzaklaştırma orijinal ölçeği geri yükler.
Matt

Yanıtlar:


126

Daha iyi çözüm, zumdaki değişime göre görünümün konumunu basitçe hareket ettirmektir. Zum noktası basitçe eski zumdaki ve yeni zumdaki aynı kalmak istediğiniz noktadır. Yani önceden yakınlaştırılmış görüntü alanı ve yakınlaştırılmış görüntü alanı görüntü alanına göre aynı yakınlaştırma noktasına sahiptir. Kökeni göre ölçeklendirdiğimiz göz önüne alındığında. Görüntü alanı konumunu buna göre ayarlayabilirsiniz:

scalechange = newscale - oldscale;
offsetX = -(zoomPointX * scalechange);
offsetY = -(zoomPointY * scalechange);

Böylece, yakınlaştırdığınızda, yakınlaştırdığınız noktaya göre ne kadar yakınlaştırdığınıza bağlı olarak aşağı ve sağa kaydırabilirsiniz.

resim açıklamasını buraya girin


2
Kes ve yapıştır kodundan daha değerli olanı, en iyi çözümün ne olduğunu ve özellikle üç satır uzunluğunda bagaj olmadan neden çalıştığını açıklamaktır.
Tatarize

2
scalechange = yeni ölçek / eski ölçek?
Tejesh Alimilli

4
Ayrıca, pan-zoom bileşeni gibi bir harita elde etmek isteyenler için eklemek istiyorum, fare X, Y (mousePosRelativeToContainer - currentTransform) / currentScale aksi takdirde geçerli fare konumunu kapsayıcıya göre tedavi edecektir.
Gilad

1
Evet, bu matematik zumun yanı sıra tava kökeni ile ilgili koordinatlarda olduğunu varsayar. Görünüm penceresine göreli olarak uygun şekilde ayarlamanız gerekir. Doğru matematik zoomPoint = (mousePosRelativeToContainer + currentTranslation) olduğunu varsayalım. Bu matematik aynı zamanda başlangıç ​​noktasının alanın sol üst köşesinde olduğunu varsayar. Ancak, basitlik göz önüne alındığında, biraz atipik durumlar için ayarlama yapmak çok daha kolaydır.
Tatarize

1
@ C.Finke İkinci olarak ctx içerisindeki çevirileri kullanmaktır. Her şeyi aynı boyutta ve aynı pozisyonlarda çiziyorsunuz. Ancak, javascript tuvalindeki matris çarpımlarını, içeriği kaydırmak ve ölçeğini (yakınlaştırmak) ayarlamak için kullanmanız yeterlidir. Böylece tüm şekilleri farklı bir konumda yeniden çizmek yerine. Onları aynı yere çiziyor ve javascript içindeki görünümü taşıyorsunuz. Bu yöntem ayrıca fare olaylarını almanızı ve bunları geriye çevirmenizi gerektirir. Böylece tavayı çıkarır, sonra faktörü zumla tersine çevirirsiniz.
Tatarize

68

Sonunda çözdü:

var zoomIntensity = 0.2;

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = 600;
var height = 200;

var scale = 1;
var originx = 0;
var originy = 0;
var visibleWidth = width;
var visibleHeight = height;


function draw(){
    // Clear screen to white.
    context.fillStyle = "white";
    context.fillRect(originx,originy,800/scale,600/scale);
    // Draw the black square.
    context.fillStyle = "black";
    context.fillRect(50,50,100,100);
}
// Draw loop at 60FPS.
setInterval(draw, 1000/60);

canvas.onwheel = function (event){
    event.preventDefault();
    // Get mouse offset.
    var mousex = event.clientX - canvas.offsetLeft;
    var mousey = event.clientY - canvas.offsetTop;
    // Normalize wheel to +1 or -1.
    var wheel = event.deltaY < 0 ? 1 : -1;

    // Compute zoom factor.
    var zoom = Math.exp(wheel*zoomIntensity);
    
    // Translate so the visible origin is at the context's origin.
    context.translate(originx, originy);
  
    // Compute the new visible origin. Originally the mouse is at a
    // distance mouse/scale from the corner, we want the point under
    // the mouse to remain in the same place after the zoom, but this
    // is at mouse/new_scale away from the corner. Therefore we need to
    // shift the origin (coordinates of the corner) to account for this.
    originx -= mousex/(scale*zoom) - mousex/scale;
    originy -= mousey/(scale*zoom) - mousey/scale;
    
    // Scale it (centered around the origin due to the trasnslate above).
    context.scale(zoom, zoom);
    // Offset the visible origin to it's proper position.
    context.translate(-originx, -originy);

    // Update scale and others.
    scale *= zoom;
    visibleWidth = width / scale;
    visibleHeight = height / scale;
}
<canvas id="canvas" width="600" height="200"></canvas>

@Tatarize'ın işaret ettiği gibi, anahtar, zum noktası (fare işaretçisi) zumdan sonra aynı yerde kalacak şekilde eksen konumunu hesaplamaktır.

Başlangıçta fare mouse/scaleköşeden uzakta , farenin altındaki noktanın zumdan sonra aynı yerde kalmasını istiyoruz, ancak bu mouse/new_scaleköşeden uzakta. Bu nedenle, bunu originhesaba katmak için (köşenin koordinatları) kaydırmamız gerekir .

originx -= mousex/(scale*zoom) - mousex/scale;
originy -= mousey/(scale*zoom) - mousey/scale;
scale *= zoom

Kalan kodun daha sonra ölçeklendirmeyi uygulaması ve çizimin köşeye tuval köşesine denk gelmesi için çizim bağlamına çevirmesi gerekir.


Teşekkürler ahbap, kodunuzu bulmadan önce neredeyse 2 gün kaybettiniz
Velaro

Hey ben sadece böyle bir şey arıyordum ve sadece stoked sen kırık olduğunu söylemek istedim!
chrisallick

26

Bu aslında (matematik olarak) çok zor bir problem ve neredeyse aynı şey üzerinde çalışıyorum. Stackoverflow benzer bir soru sordum ama hiçbir yanıt aldım, ama DocType (HTML / CSS için StackOverflow) gönderildi ve bir yanıt aldım. Bir göz atın http://doctype.com/javascript-image-zoom-css3-transforms-calculate-origin-example

Bunu yapan bir jQuery eklentisi oluşturmanın ortasındayım (CSS3 Dönüşümlerini kullanarak Google Haritalar tarzı zum). Fare imlecine biraz yakınlaştım, hala kullanıcının tuvali Google Haritalar'da yapabileceğiniz gibi sürüklemesine izin vermeyi anlamaya çalışıyorum. Çalıştığımda kodu buraya göndereceğim, ancak fare-zoom-to-point kısmı için yukarıdaki bağlantıya göz atın.

Canvas bağlamında ölçek ve çeviri yöntemleri olduğunu fark etmedim, CSS3 kullanarak aynı şeyi elde edebilirsiniz örn. jQuery kullanarak:

$('div.canvasContainer > canvas')
    .css('-moz-transform', 'scale(1) translate(0px, 0px)')
    .css('-webkit-transform', 'scale(1) translate(0px, 0px)')
    .css('-o-transform', 'scale(1) translate(0px, 0px)')
    .css('transform', 'scale(1) translate(0px, 0px)');

CSS3 dönüşüm başlangıç ​​noktasını 0, 0 (-moz-dönüşüm başlangıç ​​noktası: 0 0) olarak ayarladığınızdan emin olun. CSS3 dönüşümünü kullanmak, herhangi bir şeyi yakınlaştırmanıza olanak tanır, sadece konteyner DIV'nin taşmaya ayarlandığından emin olun: yakınlaştırılmış kenarların kenarlardan dökülmesini durdurmak için gizlidir.

CSS3 dönüşümlerini veya tuvalin kendi ölçek ve çeviri yöntemlerini kullanmak size kalmış, ancak hesaplamalar için yukarıdaki bağlantıyı kontrol edin.


Güncelleme: Meh! Bir bağlantıyı izlemenizi sağlamak yerine kodu buraya göndereceğim:

$(document).ready(function()
{
    var scale = 1;  // scale of the image
    var xLast = 0;  // last x location on the screen
    var yLast = 0;  // last y location on the screen
    var xImage = 0; // last x location on the image
    var yImage = 0; // last y location on the image

    // if mousewheel is moved
    $("#mosaicContainer").mousewheel(function(e, delta)
    {
        // find current location on screen 
        var xScreen = e.pageX - $(this).offset().left;
        var yScreen = e.pageY - $(this).offset().top;

        // find current location on the image at the current scale
        xImage = xImage + ((xScreen - xLast) / scale);
        yImage = yImage + ((yScreen - yLast) / scale);

        // determine the new scale
        if (delta > 0)
        {
            scale *= 2;
        }
        else
        {
            scale /= 2;
        }
        scale = scale < 1 ? 1 : (scale > 64 ? 64 : scale);

        // determine the location on the screen at the new scale
        var xNew = (xScreen - xImage) / scale;
        var yNew = (yScreen - yImage) / scale;

        // save the current screen location
        xLast = xScreen;
        yLast = yScreen;

        // redraw
        $(this).find('div').css('-moz-transform', 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')')
                           .css('-moz-transform-origin', xImage + 'px ' + yImage + 'px')
        return false;
    });
});

Tabii ki tuval ölçeğini ve çeviri yöntemlerini kullanmak için uyarlamanız gerekir.


Güncelleme 2: Çeviri ile birlikte dönüştürme-orijini kullandığımı fark ettim. Sadece ölçeği kullanan ve kendi çevirisini kullanan bir sürümü uygulamayı başardım, buradan kontrol edin http://www.dominicpettifer.co.uk/Files/Mosaic/MosaicTest.html Görüntülerin indirilmesini bekleyin, ardından kullanın yakınlaştırmak için fare tekerleği, görüntüyü sürükleyerek de kaydırma destekler. CSS3 Dönüşümleri kullanıyor, ancak Tuvaliniz için aynı hesaplamaları kullanabilmeniz gerekir.


nihayet çözdü, başka bir şey yapmanın yaklaşık 2 hafta sonra beni 3 dakika sürdü
csiz

@Synday Ironfoot bağlantısı güncellemesinde çalışmıyor. Bu bağlantı: dominicpettifer.co.uk/Files/Mosaic/MosaicTest.html Bu çürümeyi istiyorum. Kodu buraya gönderebilir misiniz? teşekkürler
Bogz

2
bugün itibarıyla (Eylül.2014) MosaicTest.html bağlantısı kesildi.
Chris

mozaik demo gitti. Genellikle vanilya js kullanıyorum, jQuery kullanmıyorum. $ (this) ne anlama geliyor? .body.offsetTop? Foreverscape.com projemin bundan gerçekten fayda sağlayabileceği mozaik demosunu gerçekten görmek istiyorum.
FlavorScape

2
Mozaik demo sayfası archive.org'a kaydedildi: web.archive.org/web/20130126152008/http://…
Chris

9

Ben muhtemelen başlamak için sadece OpenGL matrisleri kullanmış olmalıydı c ++ kullanarak bu sorunla karşılaştım ... neyse, eğer kaynağı sol üst köşesi olan bir kontrol kullanıyorsanız ve pan / zoom istiyorum google maps gibi, düzen (olay işleyicim olarak allegro kullanarak):

// initialize
double originx = 0; // or whatever its base offset is
double originy = 0; // or whatever its base offset is
double zoom = 1;

.
.
.

main(){

    // ...set up your window with whatever
    //  tool you want, load resources, etc

    .
    .
    .
    while (running){
        /* Pan */
        /* Left button scrolls. */
        if (mouse == 1) {
            // get the translation (in window coordinates)
            double scroll_x = event.mouse.dx; // (x2-x1) 
            double scroll_y = event.mouse.dy; // (y2-y1) 

            // Translate the origin of the element (in window coordinates)      
            originx += scroll_x;
            originy += scroll_y;
        }

        /* Zoom */ 
        /* Mouse wheel zooms */
        if (event.mouse.dz!=0){    
            // Get the position of the mouse with respect to 
            //  the origin of the map (or image or whatever).
            // Let us call these the map coordinates
            double mouse_x = event.mouse.x - originx;
            double mouse_y = event.mouse.y - originy;

            lastzoom = zoom;

            // your zoom function 
            zoom += event.mouse.dz * 0.3 * zoom;

            // Get the position of the mouse
            // in map coordinates after scaling
            double newx = mouse_x * (zoom/lastzoom);
            double newy = mouse_y * (zoom/lastzoom);

            // reverse the translation caused by scaling
            originx += mouse_x - newx;
            originy += mouse_y - newy;
        }
    }
}  

.
.
.

draw(originx,originy,zoom){
    // NOTE:The following is pseudocode
    //          the point is that this method applies so long as
    //          your object scales around its top-left corner
    //          when you multiply it by zoom without applying a translation.

    // draw your object by first scaling...
    object.width = object.width * zoom;
    object.height = object.height * zoom;

    //  then translating...
    object.X = originx;
    object.Y = originy; 
}

9

Tatarize'nin cevabını seviyorum , ama bir alternatif sunacağım. Bu önemsiz bir doğrusal cebir problemidir ve sunduğum yöntem pan, zoom, eğim vb. İle iyi çalışır. Yani, görüntünüz zaten dönüştürülmüşse iyi çalışır.

Bir matris ölçeklendiğinde ölçek nokta (0, 0) konumundadır. Dolayısıyla, bir görüntünüz varsa ve bunu 2 katına kadar ölçeklerseniz, sağ alt nokta hem x hem de y yönlerinde iki katına çıkar ([0, 0] görüntünün sol üst köşesi olduğu kuralını kullanarak).

Bunun yerine görüntüyü merkeze yakınlaştırmak isterseniz, bir çözüm aşağıdaki gibidir: (1) görüntüyü, merkezi (0, 0) olacak şekilde çevirin; (2) görüntüyü x ve y faktörlerine göre ölçeklendirir; (3) görüntüyü geri çevirir. yani

myMatrix
  .translate(image.width / 2, image.height / 2)    // 3
  .scale(xFactor, yFactor)                         // 2
  .translate(-image.width / 2, -image.height / 2); // 1

Daha soyut olarak, aynı strateji her nokta için geçerlidir. Örneğin, görüntüyü P noktasından ölçeklemek istiyorsanız:

myMatrix
  .translate(P.x, P.y)
  .scale(xFactor, yFactor)
  .translate(-P.x, -P.y);

Ve son olarak, görüntü zaten bir şekilde dönüştürülmüşse (örneğin, döndürülmüş, eğrilmiş, çevrilmiş veya ölçeklenmişse), o zaman mevcut dönüşümün korunması gerekir. Özellikle, yukarıda tanımlanan dönüşümün akım dönüşümü ile çarpımı (veya sağ çarpımı) gerekir.

myMatrix
  .translate(P.x, P.y)
  .scale(xFactor, yFactor)
  .translate(-P.x, -P.y)
  .multiply(myMatrix);

İşte aldın. İşte bunu gösteren bir kütle. Fare tekerleğini noktalara kaydırın ve sürekli olarak kaldıklarını göreceksiniz. (Yalnızca Chrome'da test edilmiştir.) Http://plnkr.co/edit/3aqsWHPLlSXJ9JCcJzgH?p=preview


1
Söylemeliyim ki, eğer afin bir dönüşüm matrisiniz varsa, bunu coşkuyla kullanın. Birçok dönüşüm matrisi, tam olarak bunu yapan zoom (sx, sy, x, y) işlevlerine bile sahip olacaktır. Kullanmak için bir tane verilmezse neredeyse bir tane pişirmeye değer.
Ağustos'ta Tatarize

Aslında, bu çözümü kullandığım kodda, o zamandan beri bir matris sınıfıyla değiştirildiğini itiraf ediyorum. Ve bu kesin şeyi birden çok kez yaptım ve en az iki kez matris dersleri pişirdim. ( github.com/EmbroidePy/pyembroidery/blob/master/pyembroidery/… ), ( github.com/EmbroidePy/EmbroidePy/blob/master/embroidepy/… ). Tam olarak bu işlemlerden daha karmaşık bir şey istiyorsanız, bir matris temel olarak doğru cevaptır ve lineer cebir üzerinde bir sapınız olduğunda, bu cevabın aslında en iyi cevap olduğunu anlarsınız.
18'de

6

İşte merkez odaklı bir görüntü için çözümüm:

var MIN_SCALE = 1;
var MAX_SCALE = 5;
var scale = MIN_SCALE;

var offsetX = 0;
var offsetY = 0;

var $image     = $('#myImage');
var $container = $('#container');

var areaWidth  = $container.width();
var areaHeight = $container.height();

$container.on('wheel', function(event) {
    event.preventDefault();
    var clientX = event.originalEvent.pageX - $container.offset().left;
    var clientY = event.originalEvent.pageY - $container.offset().top;

    var nextScale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, scale - event.originalEvent.deltaY / 100));

    var percentXInCurrentBox = clientX / areaWidth;
    var percentYInCurrentBox = clientY / areaHeight;

    var currentBoxWidth  = areaWidth / scale;
    var currentBoxHeight = areaHeight / scale;

    var nextBoxWidth  = areaWidth / nextScale;
    var nextBoxHeight = areaHeight / nextScale;

    var deltaX = (nextBoxWidth - currentBoxWidth) * (percentXInCurrentBox - 0.5);
    var deltaY = (nextBoxHeight - currentBoxHeight) * (percentYInCurrentBox - 0.5);

    var nextOffsetX = offsetX - deltaX;
    var nextOffsetY = offsetY - deltaY;

    $image.css({
        transform : 'scale(' + nextScale + ')',
        left      : -1 * nextOffsetX * nextScale,
        right     : nextOffsetX * nextScale,
        top       : -1 * nextOffsetY * nextScale,
        bottom    : nextOffsetY * nextScale
    });

    offsetX = nextOffsetX;
    offsetY = nextOffsetY;
    scale   = nextScale;
});
body {
    background-color: orange;
}
#container {
    margin: 30px;
    width: 500px;
    height: 500px;
    background-color: white;
    position: relative;
    overflow: hidden;
}
img {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    max-width: 100%;
    max-height: 100%;
    margin: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="container">
    <img id="myImage" src="http://s18.postimg.org/eplac6dbd/mountain.jpg">
</div>


4

Scale () ve translate () yerine setTransform () kullanan bunu yapmanın alternatif bir yolu. Her şey aynı nesnede saklanır. Kanvasın sayfada 0,0 olduğu varsayılır, aksi takdirde konumunu sayfa kablolarından çıkarmanız gerekir.

this.zoomIn = function (pageX, pageY) {
    var zoomFactor = 1.1;
    this.scale = this.scale * zoomFactor;
    this.lastTranslation = {
        x: pageX - (pageX - this.lastTranslation.x) * zoomFactor,
        y: pageY - (pageY - this.lastTranslation.y) * zoomFactor
    };
    this.canvasContext.setTransform(this.scale, 0, 0, this.scale,
                                    this.lastTranslation.x,
                                    this.lastTranslation.y);
};
this.zoomOut = function (pageX, pageY) {
    var zoomFactor = 1.1;
    this.scale = this.scale / zoomFactor;
    this.lastTranslation = {
        x: pageX - (pageX - this.lastTranslation.x) / zoomFactor,
        y: pageY - (pageY - this.lastTranslation.y) / zoomFactor
    };
    this.canvasContext.setTransform(this.scale, 0, 0, this.scale,
                                    this.lastTranslation.x,
                                    this.lastTranslation.y);
};

Kaydırmayı işlemek için eşlik eden kod:

this.startPan = function (pageX, pageY) {
    this.startTranslation = {
        x: pageX - this.lastTranslation.x,
        y: pageY - this.lastTranslation.y
    };
};
this.continuePan = function (pageX, pageY) {
    var newTranslation = {x: pageX - this.startTranslation.x,
                          y: pageY - this.startTranslation.y};
    this.canvasContext.setTransform(this.scale, 0, 0, this.scale,
                                    newTranslation.x, newTranslation.y);
};
this.endPan = function (pageX, pageY) {
    this.lastTranslation = {
        x: pageX - this.startTranslation.x,
        y: pageY - this.startTranslation.y
    };
};

Cevabı kendiniz türetmek için, aynı sayfa koordinatlarının yakınlaştırmadan önce ve sonra aynı tuval koordinatlarıyla eşleşmesi gerektiğini düşünün. O zaman bu denklemden başlayarak bazı cebirler yapabilirsiniz:

(pageCoords - çeviri) / scale = canvasCoords


3

Burada ayrı ayrı resim çizme ve hareket ettirme - için bazı bilgiler koymak istiyorum.

Bu, yakınlaştırmaları ve görünüm penceresinin konumunu saklamak istediğinizde yararlı olabilir.

İşte çekmece:

function redraw_ctx(){
   self.ctx.clearRect(0,0,canvas_width, canvas_height)
   self.ctx.save()
   self.ctx.scale(self.data.zoom, self.data.zoom) // 
   self.ctx.translate(self.data.position.left, self.data.position.top) // position second
   // Here We draw useful scene My task - image:
   self.ctx.drawImage(self.img ,0,0) // position 0,0 - we already prepared
   self.ctx.restore(); // Restore!!!
}

Dikkat ölçeği öncelikle OLMALIDIR .

Ve işte yakınlaştırıcı:

function zoom(zf, px, py){
    // zf - is a zoom factor, which in my case was one of (0.1, -0.1)
    // px, py coordinates - is point within canvas 
    // eg. px = evt.clientX - canvas.offset().left
    // py = evt.clientY - canvas.offset().top
    var z = self.data.zoom;
    var x = self.data.position.left;
    var y = self.data.position.top;

    var nz = z + zf; // getting new zoom
    var K = (z*z + z*zf) // putting some magic

    var nx = x - ( (px*zf) / K ); 
    var ny = y - ( (py*zf) / K);

    self.data.position.left = nx; // renew positions
    self.data.position.top = ny;   
    self.data.zoom = nz; // ... and zoom
    self.redraw_ctx(); // redraw context
    }

ve elbette bir tetikleyiciye ihtiyacımız olacak:

this.my_cont.mousemove(function(evt){
    if (is_drag){
        var cur_pos = {x: evt.clientX - off.left,
                       y: evt.clientY - off.top}
        var diff = {x: cur_pos.x - old_pos.x,
                    y: cur_pos.y - old_pos.y}

        self.data.position.left += (diff.x / self.data.zoom);  // we want to move the point of cursor strictly
        self.data.position.top += (diff.y / self.data.zoom);

        old_pos = cur_pos;
        self.redraw_ctx();

    }


})

3
if(wheel > 0) {
    this.scale *= 1.1; 
    this.offsetX -= (mouseX - this.offsetX) * (1.1 - 1);
    this.offsetY -= (mouseY - this.offsetY) * (1.1 - 1);
}
else {
    this.scale *= 1/1.1; 
    this.offsetX -= (mouseX - this.offsetX) * (1/1.1 - 1);
    this.offsetY -= (mouseY - this.offsetY) * (1/1.1 - 1);
}

2

İşte PIXI.js kullanarak @ tatarize yanıtının kod uygulaması. Çok büyük bir görüntünün bir parçası (örneğin google haritalar tarzı) bakarak bir görünüm var.

$canvasContainer.on('wheel', function (ev) {

    var scaleDelta = 0.02;
    var currentScale = imageContainer.scale.x;
    var nextScale = currentScale + scaleDelta;

    var offsetX = -(mousePosOnImage.x * scaleDelta);
    var offsetY = -(mousePosOnImage.y * scaleDelta);

    imageContainer.position.x += offsetX;
    imageContainer.position.y += offsetY;

    imageContainer.scale.set(nextScale);

    renderer.render(stage);
});
  • $canvasContainer benim html konteynırım.
  • imageContainer içinde resim bulunan PIXI kabım.
  • mousePosOnImage yalnızca görüntü bağlantı noktasına değil, tüm görüntüye göre fare konumudur.

Fare pozisyonunu şu şekilde aldım:

  imageContainer.on('mousemove', _.bind(function(ev) {
    mousePosOnImage = ev.data.getLocalPosition(imageContainer);
    mousePosOnViewport.x = ev.data.originalEvent.offsetX;
    mousePosOnViewport.y = ev.data.originalEvent.offsetY;
  },self));

0

Yakınlaştırmadan önce ve sonra dünya uzayında (ekran uzayının aksine) noktayı almanız ve ardından delta ile çevirmeniz gerekir.

mouse_world_position = to_world_position(mouse_screen_position);
zoom();
mouse_world_position_new = to_world_position(mouse_screen_position);
translation += mouse_world_position_new - mouse_world_position;

Fare konumu ekran uzayında olduğundan, onu dünya uzayına dönüştürmeniz gerekir. Basit dönüştürme buna benzer olmalıdır:

world_position = screen_position / scale - translation

0

kaydırma çubuğunun konumunu yakınlaştırdıktan sonra göstermeniz gereken noktaya doğru işlemek için scrollto (x, y) işlevini kullanabilirsiniz. fare konumunu bulmak için event.clientX ve event.clientY öğesini kullanın. Bu sana yardım edecek


0

Önemli bir şey ... eğer böyle bir şeyiniz varsa:

body {
  zoom: 0.9;
}

Tuvaldeki eşdeğer şeyi yapmanız gerekir:

canvas {
  zoom: 1.1;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.