1. #41
    Sencha User
    Join Date
    Dec 2011
    Location
    Brazil
    Posts
    104
    Vote Rating
    0
    Perdiga is an unknown quantity at this point

      0  

    Default


    ok i am waiting your code .. if you need any help i can help you

    i am test your last version and i there is a issue with the scorller yet
    and we need to centralize de image better like if the image.size is diferrent of the display size, the zoom aplicado não aplica a translação, e assim fica sempre centralizado

    what do you think?

    I was seeingthe operation in ios think by default the minimum size of the image could be the display size

  2. #42
    Sencha User armode's Avatar
    Join Date
    Nov 2011
    Location
    Germany / Darmstadt
    Posts
    64
    Vote Rating
    4
    armode is on a distinguished road

      0  

    Default


    I updated the hopefully final code in my posting here
    I have no more bugs, but I'm glad if you could test it!

    What do you mean, with to better centralize the image? At the moment the image will be first resized to the smallest value (screen width/height); that works fine for me!?

    I think a resizing after rotation would be nice and at the moment, I add zoomIn/zoomOut Buttons for Android

  3. #43
    Sencha User
    Join Date
    Dec 2011
    Location
    Brazil
    Posts
    104
    Vote Rating
    0
    Perdiga is an unknown quantity at this point

      0  

    Default


    look this, in bold what i changed . i am working now in rotation event
    there is a issue yet... sometimes cuts the image when you resize

    Code:
            Ext.define('Arkivus.ImageViewer',{        
        extend: 'Ext.Container',
        config: {
                doubleTapScale: 1
                ,maxScale: 4
                ,loadingMask: true
                ,previewSrc: false
                ,resizeOnLoad:true
                ,imageSrc: false
                ,initOnActivate: false
                ,cls: 'imageBox'
                ,scrollable: 'both'            
                ,html: '<figure><img></figure>'
        }
        ,xtype: 'imageviewer'
        ,initialize: function() {
            if(this.initOnActivate)
                this.addListener('activate', this.initViewer, this, {delay: 10, single: true});
            else
                this.addListener('painted', this.initViewer, this, {delay: 10, single: true});        
        }
        
        ,initViewer: function() {
            
            //disable scroller
            var scroller = this.getScrollable().getScroller();
            scroller.setDisabled(true);
            
            // mask image viewer
            if(this.getLoadingMask())
                this.setMasked({
                       xtype: 'loadmask',
                });
    
    
            // retrieve DOM els
            this.figEl = this.element.down('figure');
            this.imgEl = this.figEl.down('img');
    
    
            // apply required styles
            this.figEl.setStyle({
                overflow: 'hidden'
                ,display: 'block'
                ,margin: 0
            });
    
    
            this.imgEl.setStyle({
                '-webkit-user-drag': 'none'
                ,'-webkit-transform-origin': '0 0'
                ,'visibility': 'hidden'
            });
    
    
            // show preview
            if(this.getPreviewSrc())
            {
                this.element.setStyle({
                    backgroundImage: 'url('+this.getPreviewSrc()+')'
                    ,backgroundPosition: 'center center'
                    ,backgroundRepeat: 'no-repeat'
                    ,webkitBackgroundSize: 'contain'
                });
            }
    
    
            // attach event listeners
            this.on('load', this.onImageLoad, this);
            this.imgEl.addListener({
                scope: this
                ,doubletap: this.onDoubleTap
                ,pinchstart: this.onImagePinchStart
                ,pinch: this.onImagePinch
                ,pinchend: this.onImagePinchEnd
            });    
    
    
            // load image
            if(this.getImageSrc())
                this.loadImage(this.getImageSrc());
        }
        
        ,loadImage: function(src) {    
            if(this.imgEl){
                this.imgEl.dom.src = src;
                this.imgEl.dom.onload = Ext.Function.bind(this.onLoad, this, this.imgEl, 0);
            }
            else
                this.getImageSrc() = src;
        }
    
    
        ,onLoad : function(el, e) {
            this.fireEvent('load', this, el, e);
        }
        
        ,onImageLoad: function() {
            // get viewport size
            this.viewportWidth = this.viewportWidth || this.getWidth() || this.parent.element.getWidth();
            this.viewportHeight = this.viewportHeight || this.getHeight() || this.parent.element.getHeight();
                
            // grab image size
            this.imgWidth = this.imgEl.dom.width
            this.imgHeight = this.imgEl.dom.height;
                    
            // calculate and apply initial scale to fit image to screen
            if(this.getResizeOnLoad()){
                this.scale = this.baseScale = Math.min(this.viewportWidth/this.imgWidth, this.viewportHeight/this.imgHeight);
                this.setMaxScale(this.scale*4);
            }else{
                this.scale = this.baseScale = 1;
            }
            
            // set initial translation to center
            this.translateX = this.translateBaseX = (this.viewportWidth - this.baseScale * this.imgWidth) / 2;
            this.translateY = this.translateBaseY = (this.viewportHeight - this.baseScale * this.imgHeight) / 2;
            
            // apply initial scale and translation
            this.applyTransform();
            
            // initialize scroller configuration
            this.adjustScroller();
    
    
            // show image and remove mask
            this.imgEl.setStyle({ visibility: 'visible' });
    
    
            // remove preview
            if(this.getPreviewSrc())
            {
                this.element.setStyle({
                    backgroundImage: 'none'
                });
            }
    
    
            if(this.getLoadingMask())
                this.setMasked(false);
    
    
            this.fireEvent('imageLoaded', this);
        }
        
        ,onImagePinchStart: function(ev) {
            var scroller = this.getScrollable().getScroller();
    
    
            // disable scrolling during pinch
            scroller.stopAnimation();
            scroller.setDisabled(true);
            
            // store beginning scale
            this.startScale = this.scale;
            
            // calculate touch midpoint relative to image viewport
            this.originViewportX = (ev.touches[0].pageX + ev.touches[1].pageX) / 2 - this.element.getX();
            this.originViewportY = (ev.touches[0].pageY + ev.touches[1].pageY) / 2 - this.element.getY();
            
            // translate viewport origin to position on scaled image
            this.originScaledImgX = this.originViewportX + scroller.position.x - this.translateX;
            this.originScaledImgY = this.originViewportY + scroller.position.y - this.translateY;
            
            // unscale to find origin on full size image
            this.originFullImgX = this.originScaledImgX / this.scale;
            this.originFullImgY = this.originScaledImgY / this.scale;
            
            // calculate translation needed to counteract new origin and keep image in same position on screen
            this.translateX += (-1 * ((this.imgWidth*(1-this.scale)) * (this.originFullImgX/this.imgWidth)));
            this.translateY += (-1 * ((this.imgHeight*(1-this.scale)) * (this.originFullImgY/this.imgHeight)))
        
            // apply new origin
            this.setOrigin(this.originFullImgX, this.originFullImgY);
        
            // apply translate and scale CSS
            this.applyTransform();
        }
        
        ,onImagePinch: function(ev) {
            // prevent scaling to smaller than screen size
            this.scale = Ext.Number.constrain(ev.scale * this.startScale, this.baseScale-2, this.getMaxScale());
            this.applyTransform();
        }
        
        ,onImagePinchEnd: function(ev) {
            
            // set new translation
            if(this.scale == this.baseScale)
            {
                // move to center
                this.setTranslation(this.translateBaseX, this.translateBaseY);
            }
            else
            {    
                //Resize to init size like ios
                if(this.scale < this.baseScale && this.getResizeOnLoad()){
                    this.resetZoom();
                    return;
                }
                // calculate rescaled origin
                this.originReScaledImgX = this.originScaledImgX * (this.scale / this.startScale);
                this.originReScaledImgY = this.originScaledImgY * (this.scale / this.startScale);
                
                // maintain zoom position
                this.setTranslation(this.originViewportX - this.originReScaledImgX, this.originViewportY - this.originReScaledImgY);            
            }
            // reset origin and update transform with new translation
            this.setOrigin(0, 0);
            this.applyTransform();
    
    
            // adjust scroll container
            this.adjustScroller();
        }
    
    
        
        ,onDoubleTap: function(ev, t) {
            var that = this;
            var scroller = this.getScrollable().getScroller();
            if(!this.getDoubleTapScale())
                return false;
            
            // set scale and translation
            if(this.scale > this.baseScale)
            {
                // zoom out to base view
                this.scale = this.baseScale;
                this.setTranslation(this.translateBaseX, this.translateBaseY);
                // reset origin and update transform with new translation
                this.applyTransform();
    
    
                // adjust scroll container
                this.adjustScroller();
                
                // force repaint to solve occasional iOS rendering delay
                Ext.repaint();
            }
            else
            {
                // zoom in toward tap position
                var oldScale = this.scale
                    ,newScale = this.baseScale*4
                    ,originViewportX = ev ? (ev.pageX - this.element.getX()) : 0
                    ,originViewportY = ev ? (ev.pageY - this.element.getY()) : 0
                    ,originScaledImgX = originViewportX + scroller.position.x - this.translateX
                    ,originScaledImgY = originViewportY + scroller.position.y - this.translateY
                    ,originReScaledImgX = originScaledImgX * (newScale / oldScale)
                    ,originReScaledImgY = originScaledImgY * (newScale / oldScale);
                
                this.scale = newScale;
                
                //smoothes the transition
                setTimeout(function(){
                    that.setTranslation(originViewportX - originReScaledImgX, originViewportY - originReScaledImgY);
                    // reset origin and update transform with new translation
                    that.applyTransform();
    
    
                    // adjust scroll container
                    that.adjustScroller();
                    
                    // force repaint to solve occasional iOS rendering delay
                    Ext.repaint();
                },50)
                
            }
                
            
        }
        
        ,setOrigin: function(x, y) {
            this.imgEl.dom.style.webkitTransformOrigin = x+'px '+y+'px';
        }
        
        ,setTranslation:  function(translateX, translateY) {
            this.translateX = translateX;
            this.translateY = translateY;
                
            // transfer negative translations to scroll offset
            this.scrollX = this.scrollY = 0;
            
            if(this.translateX < 0)
            {
                this.scrollX = this.translateX;
                this.translateX = 0;
            }
            if(this.translateY < 0)
            {
                this.scrollY = this.translateY;
                this.translateY = 0;
            }
        }
        
        ,resetZoom:function(){
            //Resize to init size like ios
            this.scale = this.baseScale;
            
            this.setTranslation(this.translateBaseX, this.translateBaseY);
            
            // reset origin and update transform with new translation
            this.setOrigin(0, 0);
            this.applyTransform();
    
    
            // adjust scroll container
            this.adjustScroller();
            
        }
        ,rotate:function(){
            // get viewport size
            this.viewportWidth = this.parent.element.getWidth() ||this.viewportWidth || this.getWidth();
            this.viewportHeight = this.parent.element.getHeight() || this.viewportHeight || this.getHeight();
    
    
            // grab image size
            this.imgWidth = this.imgEl.dom.width
            this.imgHeight = this.imgEl.dom.height;
                    
            // calculate and apply initial scale to fit image to screen
            if(this.getResizeOnLoad()){
                this.scale = this.baseScale = Math.min(this.viewportWidth/this.imgWidth, this.viewportHeight/this.imgHeight);
                this.setMaxScale(this.scale*4);
            }else{
                this.scale = this.baseScale = 1;
            }
            
            // set initial translation to center
            this.translateX = this.translateBaseX = (this.viewportWidth - this.baseScale * this.imgWidth) / 2;
            this.translateY = this.translateBaseY = (this.viewportHeight - this.baseScale * this.imgHeight) / 2;
            
            // apply initial scale and translation
            this.applyTransform();
            
            // initialize scroller configuration
            this.adjustScroller();
             
        }
    
    
        ,applyTransform: function() {
            var fixedX = Ext.Number.toFixed(this.translateX,5)
                ,fixedY = Ext.Number.toFixed(this.translateY,5)
                ,fixedScale = Ext.Number.toFixed(this.scale, 8);
            
            if(Ext.os.is.Android)
            {
                this.imgEl.dom.style.webkitTransform = 
                    //'translate('+fixedX+'px, '+fixedY+'px)'
                    //+' scale('+fixedScale+','+fixedScale+')';
                    'matrix('+fixedScale+',0,0,'+fixedScale+','+fixedX+','+fixedY+')'
            }
            else
            {
                this.imgEl.dom.style.webkitTransform =
                    'translate3d('+fixedX+'px, '+fixedY+'px, 0)'
                    +' scale3d('+fixedScale+','+fixedScale+',1)';
            }
        }
    
    
    
    
        ,adjustScroller: function() {
            var scroller = this.getScrollable().getScroller();    
            
            // disable scrolling if zoomed out completely, else enable it
            if(this.scale == this.baseScale)
                scroller.setDisabled(true);
            else
                scroller.setDisabled(false);
            
            // size container to final image size
            var boundWidth = Math.max(this.imgWidth * this.scale, this.viewportWidth);
            var boundHeight = Math.max(this.imgHeight * this.scale, this.viewportHeight);
    
    
            this.figEl.setStyle({
                width: boundWidth + 'px'
                ,height: boundHeight + 'px'
            });
            
            // update scroller to new content size
            scroller.refresh();
    
    
            // apply scroll
            var x = 0;
            if(this.scrollX){
                x = this.scrollX
            }
            var y = 0;
            if(this.scrollY){
                y = this.scrollY
            }
            scroller.scrollTo(x*-1,y*-1)
        }        
        });
    and works fine on carousel

    Code:
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>ImageViewer Example</title>
            
            <link rel="stylesheet" type="text/css" href="http://docs.sencha.com/touch/2-0/touch/resources/css/sencha-touch.css">
            <script type="text/javascript" src="http://docs.sencha.com/touch/2-0/touch/sencha-touch-all-debug.js"></script>
    
    
            <script type="text/javascript" src="ImageViewer.js"></script>
            
            <script type="text/javascript">
                Ext.application({
                
                    name: 'ImageExample'
                    
                    ,launch: function() {
                    
                        Ext.define('WPMobile.Viewport', {
                            extend: 'Ext.Carousel',
                            xtype: 'my-viewport',
                            config: {
                                fullscreen: true,
                                layout: 'fit',
                                items: [
                                    {
                                        xtype: 'imageviewer',
                                        style: {
                                            backgroundColor: '#255'
                                        },
                                        imageSrc: 'http://cdn.macrumors.com/article/2010/09/03/145454-itunes_10_icon.jpg'
                                    },
                                    {
                                        xtype: 'imageviewer',
                                        style: {
                                            backgroundColor: '#255'
                                        },
                                        imageSrc: 'http://www.baixandowallpapers.com/wallpapers/03-2011/lua-cheia-paisagem-noite-1299711122.jpg'
                                    },
                                    {
                                        xtype: 'imageviewer',
                                        style: {
                                            backgroundColor: '#255'
                                        },
                                        imageSrc: 'http://www.baixandowallpapers.com/wallpapers/03-2011/lua-cheia-paisagem-noite-1299711122.jpg'
                                    }
                                ],
                                listeners: {
                                    activeitemchange: function( container,value, oldValue,eOpts ){
                                        oldValue.resetZoom();
                                        console.log(oldValue);
                                    },
                                    resize: function( component , eOpts ){
                                        this.getActiveItem().rotate();
                                    }
                                
                                },
                            },
                            
                            onDragStart: function (e) {
                                var scroller = this.getActiveItem().getScrollable().getScroller();
                                if (e.targetTouches.length == 1 && (e.deltaX < 0 && scroller.getMaxPosition().x === scroller.position.x) || (e.deltaX > 0 && scroller.position.x == 0)) {
                                    this.callParent(arguments);
                                }
                            },
                            onDrag: function (e) {
                                if (e.targetTouches.length == 1)
                                    this.callParent(arguments);
                            },
                            onDragEnd: function (e) {
                                if (e.targetTouches.length < 2)
                                    this.callParent(arguments);
                            }
    
    
                        });
    
    
    
    
                        Ext.create('WPMobile.Viewport', {
                            id: 'viewport'
                        });              
                                         
                    }
                });
            </script>
            
            
        </head>
    
    
        <body></body>
    </html>

  4. #44
    Sencha User
    Join Date
    Dec 2011
    Location
    Brazil
    Posts
    104
    Vote Rating
    0
    Perdiga is an unknown quantity at this point

      0  

    Default


    I got a perfect version.works like the ios.
    works with carousel, resize, rotation, doubleclick.
    the final code is in the post above

    another post was opened in touch sencha forum 2 to discuss this component


    thanks to armode

  5. #45
    Sencha User
    Join Date
    Mar 2012
    Location
    Porto, Portugal
    Posts
    31
    Vote Rating
    0
    Nunoestrada is on a distinguished road

      0  

    Default


    Thak you guys, your code is amazing and works perfectly in iOS!

  6. #46
    Sencha User
    Join Date
    Oct 2008
    Posts
    70
    Vote Rating
    -2
    Trinad can only hope to improve

      0  

    Default


    Hi,

    I am looking for pinch and zoom html content, can some one tell me if this component works If I use html content instead of image.

    Thanks,
    Kumar.