2011-12-30 21 views
9

पर एक छवि स्केल करें ऐसा लगता है कि यह काफी सरल होना चाहिए, लेकिन किसी कारण से मैं अपने दिमाग को इसके चारों ओर लपेट नहीं सकता। मेरे पास "व्यूपोर्ट" div के अंदर एक छवि है, जिसमें से अतिप्रवाह संपत्ति छिपी हुई है।जावास्क्रिप्ट (jQuery) अपने कंटेनर सेंटर प्वाइंट

मैंने jQuery UI के साथ एक साधारण ज़ूमिंग और पैनिंग लागू की है, हालांकि मुझे व्यूपोर्ट के केंद्र से उत्पन्न होने के लिए ज़ूम मिलने में परेशानी हो रही है। मैंने फ़ोटोशॉप से ​​थोड़ा सा स्क्रीनकास्ट किया जिस प्रभाव को मैं पुन: उत्पन्न करने की कोशिश कर रहा हूं: http://dl.dropbox.com/u/107346/share/reference-point-zoom.mov

पीएस में आप उस बिंदु से स्केलिंग संदर्भ बिंदु को समायोजित कर सकते हैं। जाहिर है एचटीएमएल/सीएसएस/जेएस के साथ यह संभव नहीं है, इसलिए मैं प्रभाव की नकल करने के लिए उचित बाएं और शीर्ष सीएसएस मानों को खोजने की कोशिश कर रहा हूं।

यहाँ से हटाया प्रश्न में कोड, कुछ अनावश्यक बिट्स के साथ है:

एचटीएमएल

<div id="viewport"> 
    <img id="map" src="http://dl.dropbox.com/u/107346/share/fake-map.png" alt="" /> 
</div> 

<div id="zoom-control"></div> 

जावास्क्रिप्ट

$('#zoom-control').slider({ 
    min: 300, 
    max: 1020, 
    value: 300, 
    step: 24, 
    slide: function(event, ui) { 
     var old_width = $('#map').width(); 
     var new_width = ui.value; 
     var width_change = new_width - old_width; 
     $('#map').css({ 
      width: new_width, 

      // this is where I'm stuck... 
      // dividing by 2 makes the map zoom 
      // from the center, but if I've panned 
      // the map to a different location I'd 
      // like that reference point to change. 
      // So instead of zooming relative to 
      // the map image center point, it would 
      // appear to zoom relative to the center 
      // of the viewport. 
      left: "-=" + (width_change/2), 
      top: "-=" + (width_change/2) 
     }); 
    } 
}); 

यहाँ पर परियोजना है JSFiddle: http://jsfiddle.net/christiannaths/W4seR/

उत्तर

1

मैंने हमेशा the kindness of strangers पर भरोसा किया है। उचित परिवर्तन:

// Calculate the offset as a percentage, accounting for the height of the window 
var x_offset = ((map.position().left-150))/(old_width/2); 
var y_offset = ((map.position().top-150))/(old_width/2); 

var css_properties = { 
    width: new_width, 
    // Set the offset based on the existing percentage rather than 1/2 
    // then readjust for the height of the window 
    left: (new_width * x_offset /2) + 150 + "px", 
    top: (new_width * y_offset /2) + 150 + "px" 
}; 

व्यूपोर्ट इन्स्टेन्शियशन पर एक चर सेट के साथ हार्डकोडेड 150 बदलें यदि आवश्यक हो तो।

+0

शानदार! धन्यवाद :) – Christian

0

यहां एक त्वरित काम कर संस्करण है: http://jsfiddle.net/flabbyrabbit/chLkZ/

शायद नहीं neatest समाधान लेकिन, अच्छी तरह से काम करते हैं आशा है कि यह मदद करता है लगता है।

अपडेट: क्षमा करें यह केवल तभी काम करता है जब मानचित्र स्थानांतरित होने पर ज़ूम 0 होता है।

+0

हम्म, नहीं, यह वांछित, प्रारंभिक पैन और काम करता है के बाद पहले ज़ूम के रूप में काम करने के लिए प्रतीत नहीं होता है, लेकिन फिर चीजें हैं जो बाद धराशायी हो जाना शुरू करते हैं। इसके अलावा, "क्रॉसहेयर" छवि केवल "व्यूपोर्ट" div के केंद्र बिंदु को अधिक आसानी से संदर्भित करने के लिए है, अंतिम संस्करण में इसे पूरी तरह से हटा दिया जाएगा, इसलिए इसे गणनाओं में कहीं भी उपयोग नहीं किया जा सकता है। – Christian

5

यहां कामकाजी समाधान है। मैं अगले संपादन में तर्क समझाऊंगा।

समारोह तर्क:

  • सारांश: छवि के केन्द्र की स्थिति, अपेक्षाकृत याद रखें।
    चौड़ाई और ऊंचाई के लिए गणना समान है, मैं केवल height गणना
    समझाऊंगा डिटेल्ड स्पष्टीकरण केवल फ़ंक्शन तर्क का एक उदाहरण है। वास्तविक कोड, विभिन्न चर नामों के साथ उत्तर के नीचे पाया जा सकता है।

    1. #map के केंद्र (एक्स, वाई), #viewport के सापेक्ष गणना। यह offset(), height() और width() विधियों का उपयोग करके किया जा सकता है।

      // Absolute difference between the top border of #map and #viewport 
      var differenceY = viewport.offset().top - map.offset().top; 
      // We want to get the center position, so add it. 
      var centerPosition = differenceY + viewport.height() * 0.5; 
      // Don't forget about the border (3px per CSS) 
      centerPosition += 3; 
      // Calculate the relative center position of #map 
      var relativeCenterY = centerPosition/map.height(); 
      // RESULT: A relative offset. When initialized, the center of #map is at 
      // the center of #viewport, so 50% (= 0.5) 
      // Same method for relativeCenterX 
      
    2. की गणना नए शीर्ष और बाएं ऑफसेट:

      // Calculate the effect of zooming (example: zoom 1->2 = 2) 
      var relativeChange = new_width/old_width; 
      // Calculate the new height 
      var new_height = relativeChange * old_height; 
      // Calculate the `top` and `left` CSS properties. 
      // These must be negative if the upperleft corner is outside he viewport 
      // Add 50% of the #viewport's height to correctly position #map 
      // (otherwise, the center will be at the upperleft corner) 
      var newTopCss = -relativeCenterY * new_height + 0.5 * viewport.height(); 
      
    3. बदलें सीएसएस संपत्ति

      map.css("top", newTopCss); 
      

डेमो: http://jsfiddle.net/W4seR/12/

var map = $('#map'); 
var viewport = $('#viewport'); 
// Cache the size of the viewport (300x300) 
var viewport_size = { 
    x: viewport.width(), 
    y: viewport.height() 
}; 

map.draggable(); 

$('#zoom-control').slider({ 
    min: 300, 
    max: 1020, 
    value: 300, 
    step: 24, 
    create: function() { 
     map.css({ 
      'width': 300, 
      'left': 0, 
      'top': 0 
     }); 
    }, 
    slide: function(event, ui) { 
     var old_width = map.width(); 
     var old_height = map.height(); 
     var viewport_offset = viewport.offset(); 
     var offset = map.offset(); 
     offset = { 
      top: viewport_offset.top - offset.top + .5*viewport_size.y +3, 
      left: viewport_offset.left - offset.left + .5*viewport_size.x +3 
     }; 
     // Relative offsets, relative to the center! 
     offset.top = offset.top/old_height; 
     offset.left = offset.left/old_width; 

     var new_width = ui.value; 
     var relative = new_width/old_width; 
     var new_height = relative * old_height; 

     offset = { 
      top: -offset.top * new_height + .5*viewport_size.y, 
      left: -offset.left * new_width + .5*viewport_size.x 
     }; 

     var css_properties = { 
      width: new_width, 
      left: offset.left, 
      top: offset.top 
     }; 

     map.css(css_properties); 

     trace((map.position().left)); 
    } 
}); 
+0

+1 एक कामकाजी समाधान के लिए, @RSG से जवाब स्वीकार किया गया क्योंकि यह पहले आया था। बहुत बहुत धन्यवाद :) – Christian

+0

@ क्रिस्टियन मैंने तर्क के एक विचित्र स्पष्टीकरण को जोड़ा है, सिर्फ कोड नहीं। –

+0

आपको बहुत धन्यवाद, स्पष्टीकरण की बहुत सराहना की जाती है। निश्चित रूप से मुझे इसके आसपास अपने दिमाग लपेटने में मदद :) – Christian