একটি বিন্দুতে জুম বাড়ান (স্কেল এবং অনুবাদ ব্যবহার করে)


156

আমি গুগল ম্যাপে জুম করার মতো এইচটিএমএল 5 ক্যানভাসে মাউসের নীচে পয়েন্টটিতে জুম করতে সক্ষম হতে চাই । আমি কীভাবে এটি অর্জন করতে পারি?


2
আমি আমার ক্যানভাসটি জুম করার জন্য এটি ব্যবহার করেছি এবং এটি দুর্দান্ত কাজ করে! আমি কেবল যুক্ত করতে চাই, জুম পরিমাণ গণনা আপনি আশা হিসাবে না। "var জুম = 1 + চাকা / 2;" অর্থাত্ জুম ইন করার জন্য 1.5 এবং জুম আউট করার জন্য 0.5 এ ফলাফল। আমি এটি আমার সংস্করণে সম্পাদনা করেছি যাতে আমার জুমিংয়ের জন্য 1.5 এবং জুম আউট করার জন্য 1 / 1.5 রয়েছে যা জুমিংয়ের পরিমাণ এবং জুম সমান করে তোলে। সুতরাং আপনি যদি একবার জুম করেন এবং জুম ব্যাক করেন তবে আপনার জুমিংয়ের আগের মতো চিত্র থাকবে।
ক্রিস

2
নোট করুন যে এটি ফায়ারফক্সে কাজ করে না, তবে পদ্ধতিটি সহজেই jQuery মাউসওহেল প্লাগইনে প্রয়োগ করা যেতে পারে । ভাগ করে নেওয়ার জন্য ধন্যবাদ!
jhndodo

2
var zoom = ম্যাথ.পোও (1.5f, চাকা); // জুম গণনা করতে এটি ব্যবহার করুন। এর সুবিধাটি হ'ল চাকা = 2 দ্বারা জুম করা হুইল = 1 দিয়ে দু'বার জুম করার সমান। তদ্ব্যতীত, +2 দ্বারা জুম করা এবং +2 দ্বারা আউট করা আসল স্কেলটি পুনরুদ্ধার করে।
ম্যাট

উত্তর:


126

জুমের পরিবর্তনের উপর ভিত্তি করে ভিউপোর্টের অবস্থানটি সরিয়ে নেওয়া আরও ভাল সমাধান। জুম পয়েন্টটি কেবল পুরানো জুমের পয়েন্ট এবং নতুন জুম যে আপনি একই থাকতে চান is যা বলা যায় ভিউপোর্টটি প্রাক জুমড এবং ভিউপোর্ট পোস্ট জুমডের ভিউপোর্টের তুলনায় একই জুমপয়েন্ট রয়েছে। দেওয়া হয়েছে যে আমরা উত্সের তুলনায় স্কেলিং করছি। আপনি সেই অনুযায়ী ভিউপোর্টের অবস্থানটি সামঞ্জস্য করতে পারেন:

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

জুম করা পয়েন্টের তুলনায় আপনি কতটা জুম করেছেন তার একটি ফ্যাক্টর দ্বারা আপনি যখন জুম করবেন তখন সত্যিই আপনি নীচে এবং ডানদিকে প্যান করতে পারেন।

এখানে চিত্র বর্ণনা লিখুন


2
কাট এবং পেস্ট কোডের চেয়ে মূল্যবান হ'ল সর্বোত্তম সমাধানটি কী এবং ব্যাগবিহীন কেন এটি কাজ করে বিশেষত এটি যদি তিন লাইন দীর্ঘ হয় তবে তার ব্যাখ্যা।
তাতারাইজ করুন

2
স্কেলচেঞ্জ = নিউজকেল / পুরাতন?
তেজেশ আলিমিলি

4
এছাড়াও, আমি প্যান-জুম উপাদানগুলির মতো একটি মানচিত্র অর্জন করতে চাইলে তাদেরকে যুক্ত করতে চাই, যে মাউস এক্স, ওয়াই হওয়া উচিত (মাউসপোসেলিলিটিও কনটেনার - কারেন্ট ট্রান্সফর্ম) / কারেন্টস্কেল অন্যথায় এটি পাত্রে সামঞ্জস্যপূর্ণ হিসাবে বর্তমান মাউস অবস্থানটিকে বিবেচনা করবে।
গিলাদ

1
হ্যাঁ, এই গণিতটি ধরে নিয়েছে যে জুমের পাশাপাশি প্যানটি মূল সম্পর্কিত প্রাসঙ্গিক স্থানে রয়েছে। যদি তারা ভিউপোর্টের সাথে তুলনামূলক হয় তবে আপনাকে অবশ্যই তাদের যথাযথভাবে সামঞ্জস্য করতে হবে। যদিও আমি মনে করি সঠিক গণিতটি হ'ল জুমপয়েন্ট = (মাউসপোস রিলেটিভটো কন্টেন্টার + কারেন্ট ট্রান্সলেশন)। এই গণিতটিও ধরে নেয় যে মূল ক্ষেত্রটি সাধারণত ক্ষেত্রের উপরের বামে হয়। তবে, সরলতার কারণে সামান্য atypical পরিস্থিতিতে সামঞ্জস্য করা আরও সহজ।
তাতারাইজ

1
@ সিফিনকে দ্বিতীয়বার এটি করা যায় সিটিএক্সের মধ্যে অনুবাদগুলি ব্যবহার করে। আপনি সবকিছু একই আকার এবং একই অবস্থানে আঁকেন। তবে, আপনি জাভাস্ক্রিপ্ট ক্যানভাসের মধ্যে প্যান এবং প্রসঙ্গের স্কেল (জুম) সেট করতে কেবল ম্যাট্রিক্সের গুণগুলি ব্যবহার করেন। সুতরাং ভিন্ন ভিন্ন জায়গায় সমস্ত আকার পুনরায় আঁকুন। আপনি তাদের একই জায়গায় আঁকুন এবং জাভাস্ক্রিপ্টের মধ্যে ভিউপোর্টটি সরান। এই পদ্ধতিটির জন্য আপনি মাউস ইভেন্টগুলি গ্রহণ এবং সেগুলি পিছনে অনুবাদ করারও প্রয়োজন। সুতরাং আপনি প্যানটি বিয়োগ করতে পারবেন, তারপরে জুমটি দিয়ে ফ্যাক্টরটি বিপরীত করুন।
টাটারাইজ

67

অবশেষে এটি সমাধান:

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 নির্দিষ্ট অক্ষ অবস্থান গনা যেমন যে জুম পয়েন্ট (মাউস পয়েন্টার) জুম পর একই জায়গায় থাকে।

মূলত মাউসটি mouse/scaleকোণার থেকে খুব দূরে রয়েছে , আমরা জুমের পরে মাউসের নীচে বিন্দু একই জায়গায় থাকতে চাই, তবে mouse/new_scaleএটি কোণার থেকে খুব দূরে। সুতরাং এটির originজন্য আমাদের অ্যাকাউন্টের (কোণার স্থানাঙ্ক) স্থানান্তর করতে হবে ।

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

তারপরে বাকী কোডটির জন্য স্কেলিং প্রয়োগ করতে হবে এবং অঙ্কিত প্রসঙ্গে অনুবাদ করতে হবে কারণ এটির উত্স ক্যানভাস কোণার সাথে মিলে যায়।


আপনাকে ধন্যবাদ কোড, আপনার কোডটি সন্ধানের আগে 2 দিন প্রায় হারিয়ে গেছে
ভেলারো

আরে আমি এই জাতীয় কিছু খুঁজছিলাম এবং কেবল স্টোকড বলতে চাইছিলাম আপনি এটি ক্র্যাক করেছেন!
ক্রিসালিক

26

এটি আসলে খুব কঠিন সমস্যা (গণিতগত) এবং আমি প্রায় একই জিনিস নিয়ে কাজ করছি। আমি স্ট্যাকওভারফ্লোতে অনুরূপ প্রশ্ন জিজ্ঞাসা করেছি কিন্তু কোনও প্রতিক্রিয়া পাইনি, তবে ডকটাইপ (এইচটিএমএল / সিএসএসের জন্য স্ট্যাকওভারফ্লো) পোস্ট করেছেন এবং একটি প্রতিক্রিয়া পেয়েছি। এটি দেখুন http://doctype.com/javascript-image-zoom-css3-transforms-calculate-origin- উদাহরণ

আমি এমন একটি jQuery প্লাগইন তৈরির মাঝখানে আছি যা এটি করে (CSS3 ট্রান্সফর্ম ব্যবহার করে গুগল ম্যাপস স্টাইল জুম)। আমি জুম থেকে মাউস কার্সারটি কিছুটা ঠিকঠাকভাবে কাজ করেছি, এখনও গুগল ম্যাপে আপনি যেমন করতে পারেন তেমন ক্যানভাসটিকে ব্যবহারকারীকে কীভাবে টেনে আনতে দেওয়া যায় তা জানার চেষ্টা করছি। আমি যখন এটি কাজ করে চলেছি আমি এখানে কোড পোস্ট করব, তবে মাউস-জুম-টু-পয়েন্ট অংশের জন্য উপরের লিঙ্কটি পরীক্ষা করে দেখুন।

আমি বুঝতে পারি না যে ক্যানভাস প্রসঙ্গে স্কেল এবং অনুবাদ পদ্ধতিগুলি রয়েছে, আপনি CSS3 উদাহরণ ব্যবহার করে একই জিনিস অর্জন করতে পারেন। 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)');

আপনি CSS3 রূপান্তর-উত্স 0, 0 তে সেট করেছেন তা নিশ্চিত করুন (-মোজ-ট্রান্সফর্ম-উত্স: 0 0)। সিএসএস 3 ট্রান্সফর্ম ব্যবহার করে যে কোনও কিছুতে আপনি জুম বাড়ান, কেবল কনটেনার ডিআইভি ওভারফ্লোতে সেট করা আছে তা নিশ্চিত করুন: পাশ থেকে জুমড প্রান্তগুলি ছড়িয়ে দেওয়া বন্ধ করতে লুকানো hidden

আপনি CSS3 রূপান্তরগুলি ব্যবহার করতে পারেন, বা ক্যানভাসের নিজস্ব স্কেল এবং অনুবাদ পদ্ধতিগুলি আপনার উপর নির্ভর করে, তবে গণনার জন্য উপরের লিঙ্কটি পরীক্ষা করুন।


আপডেট: মেহ! আপনাকে এখানে একটি লিঙ্ক অনুসরণ করার পরিবর্তে আমি এখানে কোড পোস্ট করব:

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

ক্যানভাস স্কেল এবং অনুবাদ পদ্ধতিগুলি ব্যবহার করতে আপনাকে অবশ্যই এটি খাপ খাইয়ে নিতে হবে।


আপডেট 2: সবেমাত্র লক্ষ্য করা গেছে আমি অনুবাদ সহ একসাথে রূপান্তর-উত্স ব্যবহার করছি। আমি একটি সংস্করণ যে শুধু ব্যবহারসমূহ স্কেল বাস্তবায়ন এবং তাদের নিজস্ব অনুবাদ, এটি চেক আউট এখানে পরিচালিত করেছি http://www.dominicpettifer.co.uk/Files/Mosaic/MosaicTest.html ডাউনলোড ইমেজ জন্য অপেক্ষা করুন তারপর ব্যবহার আপনার জুম করতে মাউস হুইল, চিত্রটি চারপাশে টেনে নিয়ে প্যানিং সমর্থন করে। এটি CSS3 ট্রান্সফর্ম ব্যবহার করছে তবে আপনার ক্যানভাসের জন্য আপনার একই গণনা ব্যবহার করতে সক্ষম হওয়া উচিত।


আমি অবশেষে এটি সমাধান করেছি, 2 মিনিট পরে অন্য কিছু করার পরে আমাকে 3 মিনিট সময়
লাগল

@ সিন্ডে আয়রনফুট লিঙ্কটি তার আপডেটে কাজ করছে না। এই লিঙ্কটি: ডেমোকিকপটিটিফার.কম.ফাইলেস / মোসাইক / মোসাইকটেষ্ট.চটিএমএল আমি এই প্রয়োগটি চাই। আপনি এখানে কোড পোস্ট করতে পারেন? ধন্যবাদ
বোগজ

2
আজকের হিসাবে (সেপ্টেম্বর) মোসাইকটেষ্ট.চ.টি.এম.এল এর লিঙ্কটি মারা গেছে।
ক্রিস

মোজাইক ডেমো চলে গেছে। আমি সাধারণত ভ্যানিলা জেএস ব্যবহার করি এবং jQuery নয়। $ (এটি) কী বোঝায়? ডকুমেন্ট.বডি.অফসেটটপ? আমি সত্যিই দেখতে চাই মোজাইক ডেমোটি আমার foreverscape.com প্রকল্পটি সত্যই এটি থেকে উপকৃত হতে পারে।
ফ্ল্যাওয়ারস্কেপ

2
মোজাইক ডেমো পৃষ্ঠাটি সংরক্ষণাগারটিতে
ক্রিস

9

আমি সি ++ ব্যবহার করে এই সমস্যায় পড়েছি, যা সম্ভবত আমার শুরু হওয়া উচিত ছিল না ... যাইহোক, আপনি যদি এমন কোনও নিয়ন্ত্রণ ব্যবহার করেন যার মূল বাম কোণটি, এবং আপনি প্যান / জুম চান গুগল ম্যাপের মতো এখানে লেআউট (আমার ইভেন্ট হ্যান্ডলার হিসাবে রূপক ব্যবহার করে):

// 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

আমি তাতারাইজের উত্তর পছন্দ করি তবে আমি একটি বিকল্প সরবরাহ করব। এটি একটি তুচ্ছ লিনিয়ার বীজগণিত সমস্যা, এবং আমি যে পদ্ধতিটি উপস্থাপন করি তা প্যান, জুম, স্কিউ ইত্যাদির সাথে ভালভাবে কাজ করে যা আপনার চিত্রটি ইতিমধ্যে রূপান্তরিত হয় তবে এটি ভাল কাজ করে।

যখন কোনও ম্যাট্রিক্সকে ছোট করা হয়, স্কেলটি বিন্দুতে (0, 0) হয়। সুতরাং, আপনার যদি একটি চিত্র থাকে এবং এটি 2 এর গুণক দ্বারা স্কেল করে, নীচের ডানদিকের পয়েন্টটি x এবং y উভয় দিকেই দ্বিগুণ হয়ে যাবে (কনভেনশনটি ব্যবহার করে যে চিত্রটির উপরের বামে [0, 0])

পরিবর্তে আপনি যদি কেন্দ্রটি সম্পর্কে চিত্রটি জুম করতে চান, তবে এর সমাধানটি নিম্নরূপ: (1) চিত্রটির এমন অনুবাদ করুন যে এর কেন্দ্রস্থলে রয়েছে (0, 0); (২) এক্স এবং ওয়াই ফ্যাক্টর দ্বারা চিত্রটি স্কেল করুন; (3) চিত্রটি ফিরে অনুবাদ করুন। অর্থাত

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

আরও বিমূর্তভাবে, একই কৌশল কোনও পয়েন্টের জন্য কাজ করে। যদি উদাহরণস্বরূপ, আপনি একটি বিন্দুতে চিত্রটি স্কেল করতে চান:

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

এবং সর্বশেষে, যদি চিত্রটি ইতিমধ্যে কিছু উপায়ে রূপান্তরিত হয় (উদাহরণস্বরূপ, যদি এটি ঘোরানো হয়, স্কিউড হয়, অনুবাদ করা হয় বা ছোট হয়) তবে বর্তমান রূপান্তরটি সংরক্ষণ করা দরকার। বিশেষত, উপরে বর্ণিত রূপান্তরটি বর্তমান রূপান্তর দ্বারা পোস্ট-গুণ (বা ডান-গুণ) করা দরকার।

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

ওখানে তোমার আছে। এখানে একটি নিমজ্জন রয়েছে যা এটি কার্যকরভাবে দেখায়। বিন্দুগুলিতে মাউসওয়েল দিয়ে স্ক্রোল করুন এবং আপনি দেখতে পাবেন যে তারা ধারাবাহিকভাবে রাখা হয় stay (কেবলমাত্র ক্রোমে পরীক্ষিত)) http://plnkr.co/edit/3aqsWHPLlSXJ9JCcJzgH?p= পূর্বরূপ


1
আমার অবশ্যই বলতে হবে, আপনার কাছে যদি একটি অ্যাফাইন ট্রান্সফর্মেশন ম্যাট্রিক্স উপলব্ধ থাকে তবে তা উত্সাহের সাথে ব্যবহার করুন। অনেকগুলি রূপান্তর ম্যাট্রিকগুলিতে এমনকি জুম (এসএক্স, সি, এক্স, ওয়াই) ফাংশন থাকবে যা ঠিক এটি করে। যদি আপনাকে কোনও ব্যবহারের ব্যবস্থা না দেওয়া হয় তবে এটি রান্না করা প্রায় মূল্যবান।
তাতারাইজ

আসলে, আমি স্বীকার করি যে কোডটিতে আমি এই সমাধানটি ব্যবহার করেছি, তখন থেকে এটি ম্যাট্রিক্স শ্রেণীর সাথে প্রতিস্থাপন করা হয়েছে। এবং আমি এই সঠিক জিনিসটি একাধিকবার করেছি এবং ম্যাট্রিক্স ক্লাস দু'বারের চেয়ে কম রান্না করেছি। ( github.com/EmbroidePy/pyembroidery/blob/master/pyembroidery/… ), ( github.com/EmbroidePy/EmbroidePy/blob/master/embroidepy/… )। আপনি যদি এই অপারেশনগুলির চেয়ে ঠিক আরও জটিল কিছু চান তবে একটি ম্যাট্রিক্স মূলত সঠিক উত্তর এবং একবার লিনিয়ার বীজগণিতের একটি হ্যান্ডেল পেয়ে গেলে আপনি বুঝতে পারবেন যে এই উত্তরটি আসলে সেরা উত্তর।
21

6

কেন্দ্রমুখী চিত্রের জন্য এখানে আমার সমাধান:

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

এটি করার একটি বিকল্প উপায় এখানে স্কেল () এবং অনুবাদ () এর পরিবর্তে সেট ট্রান্সফর্ম () ব্যবহার করে। সমস্ত জিনিস একই বস্তুতে সংরক্ষণ করা হয়। ক্যানভাসটি পৃষ্ঠায় 0,0-তে রয়েছে বলে ধরে নেওয়া হয়েছে, অন্যথায় আপনাকে পৃষ্ঠা অবস্থানগুলি থেকে এর অবস্থানটি বিয়োগ করতে হবে।

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

প্যানিং পরিচালনা করতে কোড সহ:

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

উত্তরটি নিজেরাই পেতে, বিবেচনা করুন যে জুমের আগে এবং পরে একই পৃষ্ঠার স্থানাঙ্কগুলির একই ক্যানভাস স্থানাঙ্কের সাথে মিল থাকা দরকার। তারপরে আপনি এই সমীকরণ থেকে শুরু করে কিছু বীজগণিত করতে পারেন:

(পেজকর্ডস - অনুবাদ) / স্কেল = ক্যানভাসকার্ডস


3

আমি তাদের জন্য এখানে কিছু তথ্য রাখতে চাই, যারা পৃথকভাবে ছবি আঁকেন এবং এটিকে জুম করে do

আপনি যখন জুম এবং ভিউপোর্টের অবস্থান সঞ্চয় করতে চান এটি কার্যকর হতে পারে।

এখানে ড্রয়ার রয়েছে:

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

বিজ্ঞপ্তি স্কেল প্রথম হতে হবে

এবং এখানে জুমার:

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
    }

এবং অবশ্যই আমাদের একটি ড্রাগার দরকার:

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

এখানে PIXI.js ব্যবহার করে @ টাটারাইজের উত্তরের একটি কোড বাস্তবায়ন's আমার কাছে একটি ভিউপোর্ট রয়েছে একটি খুব বড় চিত্রের অংশের দিকে (যেমন গুগল ম্যাপস স্টাইল)।

$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 আমার এইচটিএমএল ধারক।
  • imageContainer আমার পিক্সআই পাত্রে এটিতে ছবিটি রয়েছে।
  • mousePosOnImage পুরো ইমেজের তুলনায় মাউসের অবস্থান (কেবল ভিউ পোর্ট নয়)।

এখানে আমি কীভাবে মাউস পজিশন পেয়েছি:

  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

জুম করার আগে এবং পরে আপনাকে বিশ্ব স্থানের (পর্দার স্থানের বিপরীতে) পয়েন্টটি পেতে হবে এবং তারপরে ব-দ্বীপ দ্বারা অনুবাদ করতে হবে।

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;

মাউসের অবস্থান পর্দার স্পেসে রয়েছে, সুতরাং আপনাকে এটিকে বিশ্ব স্পেসে রূপান্তর করতে হবে। সাধারণ রূপান্তরকরণ এর সাথে একই রকম হওয়া উচিত:

world_position = screen_position / scale - translation

0

জুম করার পরে আপনাকে যে পয়েন্টটি দেখাতে হবে তার ডানদিকে স্ক্রোলবারের অবস্থানটি পরিচালনা করতে আপনি স্ক্রোলটো (x, y) ফাংশনটি ব্যবহার করতে পারেন mouse মাউস ব্যবহার ইভেন্টক্লিনএন্টএক্স এবং ইভেন্ট ক্রিয়েন্টের অবস্থান সন্ধানের জন্য। এটি আপনাকে সাহায্য করবে


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.