Memperbesar titik (menggunakan skala dan menerjemahkan)

156

Saya ingin dapat memperbesar titik di bawah mouse dalam kanvas HTML 5, seperti memperbesar di Google Maps . Bagaimana saya bisa mencapainya?

csiz
sumber
2
Saya menggunakan ini untuk memperbesar kanvas saya dan itu berhasil! Satu-satunya hal yang harus saya tambahkan adalah, bahwa perhitungan jumlah zoom tidak seperti yang Anda harapkan. "var zoom = 1 + roda / 2;" yaitu ini menghasilkan 1,5 untuk zoom in dan 0,5 untuk zoom out. Saya mengedit ini dalam versi saya sehingga saya memiliki 1,5 untuk memperbesar dan 1 / 1,5 untuk memperkecil yang membuat jumlah memperbesar dan memperkecil sama. Jadi, jika Anda memperbesar sekali dan memperbesar kembali Anda akan memiliki gambar yang sama seperti sebelum zoom.
Chris
2
Perhatikan bahwa ini tidak berfungsi pada Firefox, tetapi metode ini dapat dengan mudah diterapkan pada plugin jousery mousewheel . Terima kasih telah berbagi!
johndodo
2
var zoom = Math.pow (1.5f, wheel); // Gunakan ini untuk menghitung zoom. Ini memiliki keuntungan bahwa zoom dengan roda = 2 sama dengan zoom dua kali dengan roda = 1. Selain itu, memperbesar +2 dan keluar +2 mengembalikan skala asli.
Matt

Jawaban:

126

Solusi yang lebih baik adalah dengan hanya memindahkan posisi viewport berdasarkan perubahan zoom. Titik zoom hanyalah titik di zoom lama dan zoom baru yang Anda ingin tetap sama. Yang mengatakan viewport pra-perbesar dan viewport pasca-diperbesar memiliki zoompoint relatif sama dengan viewport. Mengingat bahwa kami menskalakan relatif terhadap asal. Anda dapat menyesuaikan posisi viewport sesuai:

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

Jadi, Anda bisa menggeser ke bawah dan ke kanan saat memperbesar, dengan faktor seberapa besar Anda memperbesar, relatif terhadap titik yang Anda perbesar.

masukkan deskripsi gambar di sini

Tatarize
sumber
2
Lebih berharga daripada memotong dan menyisipkan kode adalah penjelasan tentang apa solusi terbaik dan mengapa ia bekerja tanpa bagasi, terutama jika panjangnya tiga baris.
Tatarize
2
scalechange = newscale / oldscale?
Tejesh Alimilli
4
juga, saya ingin menambahkan bagi mereka yang ingin mencapai peta seperti komponen pan-zoom, bahwa mouse X, Y harus (mousePosRelativeToContainer - currentTransform) / currentScale jika tidak maka akan memperlakukan posisi mouse saat ini relatif terhadap wadah.
Gilad
1
Ya, matematika ini mengasumsikan bahwa zoom serta wajan berada dalam koordinat yang relevan dengan asal. Jika mereka relatif terhadap viewport Anda harus menyesuaikannya dengan tepat. Meskipun saya kira matematika yang benar adalah zoomPoint = (mousePosRelativeToContainer + currentTranslation). Matematika ini juga mengasumsikan titik asal biasanya di kiri atas bidang. Tetapi, menyesuaikan untuk situasi yang sedikit tidak lazim jauh lebih mudah mengingat kesederhanaannya.
Tatarize
1
@ C.Finke Cara kedua dapat dilakukan adalah dengan menggunakan terjemahan dalam ctx. Anda menggambar semuanya dengan ukuran yang sama dan di posisi yang sama. Tapi, Anda cukup menggunakan perkalian matriks dalam kanvas javascript untuk mengatur panci dan skala (zoom) konteks. Jadi, alih-alih menggambar ulang semua bentuk di lokasi yang berbeda. Anda menggambar mereka di tempat yang sama dan memindahkan viewport dalam javascript. Metode ini juga mengharuskan Anda untuk mengambil peristiwa mouse dan menerjemahkannya mundur. Jadi, Anda akan mengurangi wajan, lalu membalikkan faktor dengan zoom.
Tatarize
68

Akhirnya dipecahkan:

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>

Kuncinya, seperti yang ditunjukkan oleh @Tatarize , adalah untuk menghitung posisi sumbu sedemikian rupa sehingga titik zoom (penunjuk mouse) tetap berada di tempat yang sama setelah zoom.

Awalnya mouse berada pada jarak mouse/scaledari sudut, kami ingin titik di bawah mouse tetap berada di tempat yang sama setelah zoom, tetapi ini berada mouse/new_scalejauh dari sudut. Karena itu kita perlu menggeser origin(koordinat sudut) untuk memperhitungkan ini.

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

Kode yang tersisa kemudian perlu menerapkan penskalaan dan menerjemahkan ke konteks draw sehingga asalnya bertepatan dengan sudut kanvas.

csiz
sumber
Terima kasih Bung, hampir hilang 2 hari, sebelum menemukan kode Anda
Velaro
Hei saya hanya mencari sesuatu seperti ini dan hanya ingin mengatakan bahwa Anda telah memecahkannya!
chrisallick
26

Ini sebenarnya masalah yang sangat sulit (secara matematis), dan saya sedang mengerjakan hal yang hampir sama. Saya mengajukan pertanyaan serupa pada Stackoverflow tetapi tidak mendapat tanggapan, tetapi diposting di DocType (StackOverflow untuk HTML / CSS) dan mendapat tanggapan. Lihatlah http://doctype.com/javascript-image-zoom-css3-transforms-calculate-origin-example

Saya sedang membangun plugin jQuery yang melakukan ini (Google Style zoom menggunakan CSS3 Transforms). Saya memiliki bit kursor zoom ke mouse berfungsi dengan baik, masih mencoba mencari cara untuk memungkinkan pengguna untuk menyeret kanvas sekitar seperti yang dapat Anda lakukan di Google Maps. Ketika saya membuatnya berfungsi saya akan memposting kode di sini, tetapi periksa tautan di atas untuk bagian mouse-zoom-to-point.

Saya tidak menyadari ada skala dan menerjemahkan metode pada konteks Canvas, Anda dapat mencapai hal yang sama menggunakan misalnya CSS3. menggunakan jQuery:

$('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)');

Pastikan Anda mengatur CSS3 transform-origin menjadi 0, 0 (-moz-transform-origin: 0 0). Menggunakan transformasi CSS3 memungkinkan Anda memperbesar apa pun, pastikan wadah DIV diatur ke melimpah: disembunyikan untuk menghentikan tepian yang diperbesar keluar dari samping.

Apakah Anda menggunakan transformasi CSS3, atau skala sendiri dan metode menerjemahkannya terserah Anda, tetapi periksa tautan di atas untuk perhitungannya.


Pembaruan: Meh! Saya hanya akan memposting kode di sini daripada membuat Anda mengikuti tautan:

$(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;
    });
});

Anda tentu saja perlu menyesuaikannya untuk menggunakan skala kanvas dan menerjemahkan metode.


Pembaruan 2: Saya perhatikan saya menggunakan transform-origin bersama dengan translate. Saya telah berhasil mengimplementasikan versi yang hanya menggunakan skala dan menerjemahkan sendiri, periksa di sini http://www.dominicpettifer.co.uk/Files/Mosaic/MosaicTest.html Tunggu gambar untuk diunduh kemudian gunakan Anda roda mouse untuk memperbesar, juga mendukung panning dengan menyeret gambar di sekitar. Itu menggunakan CSS3 Transforms tetapi Anda harus dapat menggunakan perhitungan yang sama untuk Kanvas Anda.

Sunday Ironfoot
sumber
saya akhirnya menyelesaikannya, butuh saya 3 menit sekarang setelah sekitar 2 minggu melakukan sesuatu yang lain
csiz
Tautan @Synday Ironfoot pada pembaruannya tidak berfungsi. Tautan ini: dominicpettifer.co.uk/Files/Mosaic/MosaicTest.html saya ingin penerapan ini. Bisakah Anda memposting di sini kodenya? terima kasih
Bogz
2
pada hari ini (sept.2014) tautan ke MosaicTest.html sudah mati.
Chris
demo mosaik hilang. Saya biasanya menggunakan vanilla js dan bukan jQuery. apa yang dimaksud dengan $ (ini)? document.body.offsetTop? Saya benar-benar ingin melihat demo mosaik proyek foreverscape.com saya benar-benar bisa mendapatkan manfaat darinya.
FlavourScape
2
Halaman demo mosaik disimpan di archive.org: web.archive.org/web/20130126152008/http://…
Chris
9

Saya mengalami masalah ini menggunakan c ++, yang mungkin seharusnya saya tidak punya saya hanya menggunakan matriks OpenGL untuk memulai dengan ... anyways, jika Anda menggunakan kontrol yang asalnya adalah sudut kiri atas, dan Anda ingin pan / zoom seperti google maps, inilah tata letaknya (menggunakan allegro sebagai pengendali acara saya):

// 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; 
}
Aleksandr Albert
sumber
9

Saya suka jawaban Tatarize , tetapi saya akan memberikan alternatif. Ini adalah masalah aljabar linier sepele, dan metode yang saya sajikan bekerja dengan baik dengan pan, zoom, condong, dll. Artinya, ini berfungsi dengan baik jika gambar Anda sudah diubah.

Ketika sebuah matriks diskalakan, skala berada pada titik (0, 0). Jadi, jika Anda memiliki gambar dan menskalakannya dengan faktor 2, titik kanan bawah akan berlipat ganda dalam arah x dan y (menggunakan konvensi bahwa [0, 0] adalah kiri atas gambar).

Jika Anda ingin memperbesar gambar tentang pusat, maka solusinya adalah sebagai berikut: (1) menerjemahkan gambar sedemikian rupa sehingga pusatnya berada di (0, 0); (2) skala gambar dengan faktor x dan y; (3) menerjemahkan kembali gambar. yaitu

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

Secara lebih abstrak, strategi yang sama berfungsi untuk setiap titik. Jika, misalnya, Anda ingin skala gambar pada titik P:

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

Dan terakhir, jika gambar sudah ditransformasikan dengan cara tertentu (misalnya, jika diputar, miring, diterjemahkan, atau diskalakan), maka transformasi saat ini perlu dipertahankan. Secara khusus, transformasi yang didefinisikan di atas harus dikalikan setelahnya (atau dikalikan kanan) oleh transformasi saat ini.

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

Itu dia. Di sini ada bungkusan yang menunjukkan tindakan ini. Gulir dengan roda mouse pada titik-titik dan Anda akan melihat bahwa mereka secara konsisten tetap diam. (Diuji hanya di Chrome.) Http://plnkr.co/edit/3aqsWHPLlSXJ9JCcJzgH?p=preview

avejidah
sumber
1
Saya harus mengatakan, jika Anda memiliki matriks transformasi affine yang tersedia untuk Anda, gunakan itu dengan antusias. Banyak matriks transformasi bahkan akan memiliki fungsi zoom (sx, sy, x, y) yang melakukan hal itu. Hampir layak untuk memasak satu jika Anda tidak diberi satu untuk digunakan.
Tatarize
Bahkan, saya mengakui bahwa dalam kode saya menggunakan solusi ini, sejak itu telah diganti dengan kelas matriks. Dan saya telah melakukan hal yang tepat ini beberapa kali dan telah membuat kelas matriks tidak kurang dari dua kali. ( github.com/EmbroidePy/pyembroidery/blob/master/pyembroidery/… ), ( github.com/EmbroidePy/EmbroidePy/blob/master/embroidepy/… ). Jika Anda menginginkan sesuatu yang lebih kompleks daripada operasi-operasi ini, sebuah matriks pada dasarnya adalah jawaban yang benar dan setelah Anda menguasai aljabar linier Anda menyadari bahwa jawaban ini sebenarnya adalah jawaban terbaik.
Tatarize
6

Inilah solusi saya untuk gambar berorientasi pusat:

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>

Chris
sumber
4

Berikut cara alternatif untuk melakukannya yang menggunakan setTransform () alih-alih skala () dan terjemahkan (). Semuanya disimpan di objek yang sama. Kanvas diasumsikan sebesar 0,0 pada halaman, jika tidak Anda harus mengurangi posisinya dari coords halaman.

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

Kode pendamping untuk menangani panning:

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

Untuk mendapatkan jawabannya sendiri, pertimbangkan bahwa koordinat halaman yang sama harus cocok dengan koordinat kanvas yang sama sebelum dan sesudah zoom. Maka Anda dapat melakukan beberapa aljabar mulai dari persamaan ini:

(pageCoords - terjemahan) / scale = canvasCoords

chad
sumber
3

Saya ingin memberikan beberapa informasi kepada mereka di sini, yang secara terpisah menggambar dan memindahkannya.

Ini mungkin berguna ketika Anda ingin menyimpan zoom dan posisi viewport.

Di sini adalah laci:

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!!!
}

Skala pemberitahuan HARUS menjadi yang pertama .

Dan di sini adalah zoomer:

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
    }

dan, tentu saja, kita akan membutuhkan penyeret:

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

    }


})
Vasiliy Stavenko
sumber
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);
}
Daniel
sumber
2

Berikut ini adalah implementasi kode dari jawaban @ tatarize, menggunakan PIXI.js. Saya memiliki viewport melihat bagian dari gambar yang sangat besar (misalnya gaya google maps).

$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 adalah wadah html saya.
  • imageContainer adalah wadah PIXI saya yang memiliki gambar di dalamnya.
  • mousePosOnImage adalah posisi mouse relatif terhadap seluruh gambar (bukan hanya port tampilan).

Inilah cara saya mendapatkan posisi mouse:

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

Anda harus mendapatkan titik di ruang dunia (berlawanan dengan ruang layar) sebelum dan sesudah zoom, dan kemudian terjemahkan oleh delta.

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;

Posisi mouse ada di ruang layar, jadi Anda harus mengubahnya ke ruang dunia. Transformasi sederhana harus serupa dengan ini:

world_position = screen_position / scale - translation
Enhex
sumber
0

Anda dapat menggunakan fungsi scrollto (x, y) untuk menangani posisi scrollbar langsung ke titik yang harus ditunjukkan setelah zooming. Untuk menemukan posisi mouse gunakan event.clientX dan event.clientY. ini akan membantu Anda

Mamo Ghandi
sumber
0

Satu hal penting ... jika Anda memiliki sesuatu seperti:

body {
  zoom: 0.9;
}

Anda perlu membuat hal yang sama dalam kanvas:

canvas {
  zoom: 1.1;
}
Lucas Moyano Angelini
sumber