PDA

View Full Version : Pinch Zoom Scrollable Image



mrsunshine
14 Mar 2012, 4:11 PM
Update: i removed the first example and replaced it by a class which solves the problem

Pinch Zoom Image, creates a pinch zoom able image in a scrollable container
Can be uses with dynamic size from the height width of the container.

Features:


pinch zoom to scale the image
with scrollbars if image size need this
center scrollers while zooming (has to be improved)

Example 1:


{
flex: 1,
xtype: 'pinchzoomimage',
src: '/resources/images/casinomenu.jpg'
}


Example 2


{
xtype: 'pinchzoomimage',
src: '/resources/images/casinomenu.jpg',
width: 320,
height: 440
}


The class


/**
* Pinch Zoom Image
* creates a pinch zoom able image in a scrollable container
*
* Can be uses with dynamic size from the height width of the container
*
* @example
* {
* flex: 1,
* xtype: 'pinchzoomimage',
* src: '/resources/images/casinomenu.jpg'
* }
*
* or with fixed sizes
*
* {
* xtype: 'pinchzoomimage',
* src: '/resources/images/casinomenu.jpg',
* width: 320,
* height: 440
* }
*
*
* @author Nils Dehl <[email protected]>
* @www http://www.nils-dehl.de
*
* @version: 1.0.0
*/
Ext.define('Ux.PinchZoomImage', {
extend: 'Ext.Container',
xtype: 'pinchzoomimage',
alias: 'widget.pinchzoomimage',


config: {
/**
* Image src url
*
* @type String
*/
src: '',


/**
* height of the pinchzoom image
*
* @type int
*/
height: null,


/**
* width of the pinchzoom image
*
* @type int
*/
width: null,


scrollable: true,
listeners: {
painted: 'initImage'
}
},


/**
* init the image in the scrollable container
*
* @param {} newImageSrc
*/
initImage: function(newImageSrc) {
var height = this.getHeight() || this.element.getHeight(),
width = this.getWidth() || this.element.getWidth(),
src = this.getSrc() || newImageSrc,
image = null;


if (Ext.isString(src) && src !== '') {
image = Ext.create('Ext.Img', {
// set mode auf empty to create a real image tag
mode: '',
height: height,
width: width,
src: src,
listeners: {
pinch: {
element: 'element',
fn: this.onImagePinch


},
doubletap: {
element: 'element',
fn: this.onImageDoubletap
}
}
});


this.add(image);
}
},


/**
* reset the image to initial size
*
* @param {} e
*/
onImageDoubletap: function(e) {
var initialWidth = this.getInitialConfig('width'),
initialHeight = this.getInitialConfig('height'),
container = this,
image = this.element;




container.setWidth(initialWidth);
container.setHeight(initialHeight);
image.setWidth(initialWidth);
image.setHeight(initialHeight);
},


/**
* on image pinch scale the image size
* and set the scroller to a new position
*
* @param {} e eventobject
*/
onImagePinch: function(e) {
var initialWidth = this.getInitialConfig('width'),
initialHeight = this.getInitialConfig('height'),
newWidth = initialWidth * e.scale,
newHeight = initialHeight * e.scale,
container = this,
image = this.element,
scroller = this.up('container').getScrollable().getScroller(),
pos = scroller.getMaxPosition();




container.setWidth(newWidth);
container.setHeight(newHeight);
image.setWidth(newWidth);
image.setHeight(newHeight);
scroller.scrollTo(pos.x/2, pos.y/2);
},


/**
* if set Src is called and an
* old image exist destroy the old
* one and add the new one
*
* @param {} newImageSrc
* @param {} oldImageSrc
*/
applySrc: function(newImageSrc) {
var oldImage = this.down('img');


if (Ext.isObject(oldImage)) {
oldImage.destroy();
}


this.initImage(newImageSrc);
}


});

hotdp
15 Mar 2012, 12:13 AM
Great job!
I have some features that would be awesome to have:

It always scale from upper left corner. Its not very user friendly, is it possible to zoom from the center of the pitch location?
It behaves strange when you first zoom in, take a break and zoom some more. Looks like it starts to scale from 1 instead of the pinchend scale size. But I might be wrong here?

gkatz
15 Mar 2012, 12:19 AM
Nice...
any chance of transforming this into component structure?

mrsunshine
15 Mar 2012, 1:01 AM
It always scale from upper left corner. Its not very user friendly, is it possible to zoom from the center of the pitch location?

yeah, an idea could be to correct the scroll position while pinch i will look into this





It behaves strange when you first zoom in, take a break and zoom some more. Looks like it starts to scale from 1 instead of the pinchend scale size. But I might be wrong here?

thats at the moment cause i start with the initial with and hight it could be changed to the current width and height

mrsunshine
15 Mar 2012, 1:03 AM
Nice...
any chance of transforming this into component structure?

this will be the next step

hotdp
15 Mar 2012, 1:16 AM
yeah, an idea could be to correct the scroll position while pinch i will look into this


This is the biggest problem. I have tried some things myself but run into placements problems. If I scale from center the image container will not place the image correct. (can't scroll to the left/left-upper-corner). But I will keep hitting F5 on this thread and hope you will come up with something.

Ps. When this component is working perfectly I will try to combine it with the Carousel.

dphunkt
15 Mar 2012, 8:45 AM
I've had some success adding something similar to a carousel. I hooked in to the onItemAdd function and set up my pinch listeners there. Also, I was able to override the onDragStart function and prevent the flick to the prev/next carousel item if the image isn't scrolled all the way to the edge of its scrollable container. Still working on the resize centering issue. Resetting the scroll position keeps it centered but it's jumpy.



Ext.define('PinchCarousel', {
extend: 'Ext.Carousel',
xtype: 'slideshow',
requires: [
//'Ext.Img'
],
config: {
id: 'slideShow'
},
/*
beforeInitialize: function() {

},
*/
onItemAdd: function(item, index){
var scale, perc, size,
el = item.element;

el.on({
/*
doubletap: function(e, node, options, eOpts) {
console.log(item);
},
*/
pinchstart: function(e, node, options, eOpts) {
size = el.down('.carousel-item-img').getSize();
},
pinch: function(e, node, options, eOpts) {
var newScale = e.scale,
scroller = item.getScrollable().getScroller(),
width = size.width*newScale,
height = size.height*newScale,
pos = scroller.getMaxPosition();



if (height > 1024 || width > 1024 || height < 160 || width < 160) return;

el.down('.carousel-item-img').setSize(width, height);


//keeps it centered but jumpy
scroller.scrollTo(pos.x/2, pos.y/2);
},
pinchend: function() {
//item.getScrollable().getScroller().refresh();
}
});

this.callParent(arguments);
},
onDragStart: function(e) {
var scroller = this.getActiveItem().getScrollable().getScroller();
//ensure the image component is scrolled all the way to the edge of its scrollable container
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) {
//console.log(this.getActiveItem().getScrollable().getScroller().position.x);
if(e.targetTouches.length == 1)
this.callParent(arguments);
},
onDragEnd: function(e) {
if(e.targetTouches.length < 2)
this.callParent(arguments);
}
});

mrsunshine
15 Mar 2012, 1:11 PM
thanks for the tip with the scrollbar handling,
i added it to my code, like you said it if only to smoothed

hotdp
19 Mar 2012, 1:04 AM
Hi,
Have you guys had luck solving the center zoom issue?

mrsunshine
19 Mar 2012, 9:05 AM
i updatet the example respectively replaced it by my own class.
i added the scoller center solution from dphunkt
(http://www.sencha.com/forum/member.php?371043-dphunkt)
you can find the solution in post #1 (http://www.sencha.com/forum/showthread.php?187928-Pinch-Zoom-Scrollable-Image&p=756087&viewfull=1#post756087)

samsonasu
19 Mar 2012, 3:02 PM
Thanks for posting this, it's great! You should consider put it on github to encourage other contributions. I think it's easier to collaborate on something like github.

I modified it a bit to handle a different use case for when the container needs to be sized different from the initial image and also added a couple small feature like maximum zoom-out level and better support for non-multitouch devices. Let me know if you'd like my version, or post on github and I'll fork it :)

hotdp
19 Mar 2012, 11:08 PM
Thanks for posting this, it's great! You should consider put it on github to encourage other contributions. I think it's easier to collaborate on something like github.

I modified it a bit to handle a different use case for when the container needs to be sized different from the initial image and also added a couple small feature like maximum zoom-out level and better support for non-multitouch devices. Let me know if you'd like my version, or post on github and I'll fork it :)

Hi,
I would love to see your solution?

mrsunshine
20 Mar 2012, 1:41 AM
i will put it on github asap and yes i like to see you solution as well

gkatz
20 Mar 2012, 5:02 AM
@mrsunshine (http://www.sencha.com/forum/member.php?48799-mrsunshine)
what's the github url?
thanks

welshcathy
20 Mar 2012, 9:22 AM
Hiya,

Just read this thread this morning - then came across this really good explanation of how to pinch-zoom using matrix transformations -- if anyone is interested in replacing the use of scrollers.

http://www.youtube.com/watch?v=lcD9CF0bxyk

Details on the matrix transforms start at around 12mins.
It's a talk by Stephen Woods a Flickr frontend engineer.

gkatz
21 Mar 2012, 1:44 AM
Hiya,

Just read this thread this morning - then came across this really good explanation of how to pinch-zoom using matrix transformations -- if anyone is interested in replacing the use of scrollers.

http://www.youtube.com/watch?v=lcD9CF0bxyk


great f'ing video.
I wonder if the algorithm works as explained...

Perdiga
21 Mar 2012, 9:27 AM
Did you have same sample using your carousel to help me ? i am getting the error "TypeError: 'undefined' is not an object (evaluating 'this.getActiveItem().getScrollable().getScroller')"

Cacofoniks
3 Apr 2012, 7:20 AM
I am sorry to be so newbie, but I can not hide and help it :)

In a Touch 2 MVC app context, where should I put the custom class? ...and is it possible to use this class as an Ext.carousel.Carousel item?

Thanks!!!

Petros

Cacofoniks
9 Apr 2012, 9:04 AM
Hi dphunkt and guys, this is an amazing post. Thank you for sharing the code!!

I am getting into some trouble though. I get an error when I try to swipe the carousel:

Uncaught TypeError: Object [object Object] has no method 'getScrollable' in the JS console.

i am not sure if I use it correctly though; i have added your code to a new file PinchCarousel.js under sdk/src/carousel and added this to Main.js:


Ext.define("pinchtest.view.Main", {
extend: 'Ext.carousel.pinchcarousel',


requires:[
'Ext.Img'
],


config:{
xtype:'slideshow',
autoMaximize:true,
items: [
{

xtype:'image',
src:'resources/images/Zakkum003.jpg'




// html: '<img src="resources/images/Zakkum003.jpg" />'


},
{
xtype:'image',
src:'resources/images/Zakkum003.jpg'
// html: '<img src="resources/images/Zakkum003.jpg" />'


}
]}
// }
});

Any chance that you could maybe spot the error?

Thanks a bunch!

dphunkt
9 Apr 2012, 9:22 AM
Cacofoniks, you'll want to wrap each of your image objects inside an Ext.Container since Ext.Image doesn't have a scrollable property. Something like this:



{
xtype: 'container',
//layout: 'auto',
scrollable: {
direction: 'both',
directionLock: false,
indicators: false,
momentumEasing: {
momentum: {
acceleration: 60,
friction: 0.3
},
bounce: {
acceleration: 30,
springTension: 0.3
}
}
},
items: [
{
xtype: 'image',
//mode: '',
cls: 'carousel-item-img',
width: '320px',
height: '240px',
//centered: true,
style: {
'-webkit-background-size': 'contain',
'-webkit-backface-visibility': 'hidden',
'-webkit-perspective': '1000',
'-webkit-transform': 'translate3d(0, 0, 0)'
},
src: src
}
]
}

Cacofoniks
9 Apr 2012, 9:51 AM
dphunkt, that worked like a charm thank you very so much :)

Have you tested it in an Android device? The pinch doesn't work in my Desire (Android 2.2), is that how it is supposed to be?

Thanks again!!

Petros

Perdiga
9 Apr 2012, 10:45 AM
dphunkt, that worked like a charm thank you very so much :)

Have you tested it in an Android device? The pinch doesn't work in my Desire (Android 2.2), is that how it is supposed to be?

Thanks again!!

Petros

i am testing in my galaxy tab and works fine ...

now how can i centralize the image?

Cacofoniks
10 Apr 2012, 6:58 AM
...from what I understand the issue of central image is still to be resolved.

Is there any way that we can embed a standard JS-framework agnostic solution for pinch-zoom in Sencha, like the Zynga Scroller (http://zynga.github.com/scroller/) for example?

Thanks...

bhomass
11 Apr 2012, 9:26 AM
Hi, great class.

I have it all working except for image size.

when I use flex:1, the image if hard coded to 0 width and 0 height. I can see the style:"width:0px; height:0px; !important" attribute in the source.

when I use width: 320, height:440
it works but is the wrong format, and when I rotate the phone to a landscape orientation, the width does not adjust.

question: is flex:1 suppose to let the image display at the full size of the screen? why do I get hard coded size of 0,0? when you set a fixed width and height, are you suppose to detect the browser container size first? how do you adjust when the phone rotates?

bhomass
11 Apr 2012, 10:10 AM
I played with various width and height settings. it seems as long as I set the width to be sames as the landscape phone width, it looks decent in either direction. However, there is problem panning to the bottom of the page. Everytime I tried move the page up to see the bottom section, it snaps back by itself. any ideas?

SButts
11 Apr 2012, 11:55 AM
dphunkt, that worked like a charm thank you very so much :)

Have you tested it in an Android device? The pinch doesn't work in my Desire (Android 2.2), is that how it is supposed to be?

Thanks again!!

Petros


I think the pinch event is only supported on iOS and Android 3+.

bhomass
11 Apr 2012, 12:42 PM
pinch works on my Samsung Galaxy Nexus. only problem is pan to the bottom of the image.

SButts
11 Apr 2012, 1:11 PM
pinch works on my Samsung Galaxy Nexus. only problem is pan to the bottom of the image.

Doesn't that phone have Android 4?

bhomass
13 Apr 2012, 10:28 AM
yes, is Android 4.

no one else sees the same problem? why would the image snap back and refuses to reach the bottom?

Perdiga
13 Apr 2012, 10:33 AM
i implement this class and improve

ItemCarousel.js


Ext.define('App.ext.carousel.ItemCarousel', {
extend: 'Ext.Container',
xtype: 'itemcarousel',


config: {
src: null,
id: null,
initWidth: null,
initHeight: null,
layout: 'vbox',
scrollable: {
direction: 'both',
directionLock: false,
indicators: false,
momentumEasing: {
momentum: {
acceleration: 60,
friction: 0.3
},
bounce: {
acceleration: 30,
springTension: 0.3
}
}
},
listeners: {
painted: function () {
this.load();
},
resize:function(){
console.log(arguments,'resize')
}
}


},
load: function () {
this.removeAll();
this.add({
xtype: 'image',
cls: 'carousel-item-img',
width: this.getInitWidth(),
height: this.getInitHeight(),
style: {
'-webkit-background-size': 'contain',
'-webkit-backface-visibility': 'hidden',
'-webkit-perspective': '1000',
'-webkit-transform': 'translate3d(0, 0, 0)'
},
src: this.getSrc(),
listeners: {
load: function (img, e, eOpts) {
img.setWidth(img.imageObject.naturalWidth);
img.setHeight(img.imageObject.naturalHeight);
}
}
});
},
});



PinchCarousel


Ext.define('App.ext.carousel.PinchCarousel', {
extend: 'Ext.Carousel',
xtype: 'slideshow',


onItemAdd: function (item, index) {
var scale, perc, size,
el = item.element;


el.on({
doubletap: function (e, node, options, eOpts) {
size = el.down('.carousel-item-img').getSize();
newScale = item.parent.itemLength / size.width


width = size.width * newScale,
height = Math.round(size.height * newScale),


console.log(width, height, newScale)


el.down('.carousel-item-img').setSize(width, height);
},


pinchstart: function (e, node, options, eOpts) {
size = el.down('.carousel-item-img').getSize();
},
pinch: function (e, node, options, eOpts) {
var newScale = e.scale,
scroller = item.getScrollable().getScroller(),
width = size.width * newScale,
height = size.height * newScale,
pos = scroller.getMaxPosition();


if (height > 1920 || width > 1200 || height < 350 || width < 350) return;


el.down('.carousel-item-img').setSize(width, height);
//keeps it centered but jumpy
scroller.scrollTo(pos.x / 2, pos.y / 2);
},
pinchend: function () {
//item.getScrollable().getScroller().refresh();
},
});


this.callParent(arguments);
},
onDragStart: function (e) {
var scroller = this.getActiveItem().getScrollable().getScroller();
//ensure the image component is scrolled all the way to the edge of its scrollable container
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) {
//console.log(this.getActiveItem().getScrollable().getScroller().position.x);
if (e.targetTouches.length == 1)
this.callParent(arguments);
},
onDragEnd: function (e) {
if (e.targetTouches.length < 2)
this.callParent(arguments);
}
});


how to use


var img = Ext.create('App.ext.carousel.ItemCarousel', {
src:result.Result[i].uri,
id:'image'+i,
});
mySlideShow.add(img);


i need now centralize the image.. any suggestions?

bhomass
13 Apr 2012, 3:24 PM
I found the culprit.

pinchzoomimage is an Img inside a Container.

when setting width and height of the image, you also end up setting width and height of the container, which for some reason causes the snap back when you try to pan to the bottom.

I added the workaround by defining config parameters imageWidth and imageHeight which are applied to Img only. Now it pans like a charm.

armode
17 Apr 2012, 4:52 AM
There was a great pinch / zoom plugin for ST1 from chris, which worked fine in the end! Central zooming, adjustable scrolling bars, etc.
You can find the code on github:
https://github.com/JarvusInnovations/Jarvus.mobile.PinchCarousel/

I tried to port the plugin to ST2, but was not yet successful:
http://www.sencha.com/forum/showthread.php?137632-mostly-working-pinch-zoom-image-carousel-help-perfect-it!&p=749502&viewfull=1#post749502 (http://www.sencha.com/forum/showthread.php?137632-mostly-working-pinch-zoom-image-carousel-help-perfect-it%21&p=749502&viewfull=1#post749502)

Maybe this will help to finish the zooming issue...

armode
20 Apr 2012, 4:38 AM
I just want to announce, that I made huge progress in porting the pinch / zoom plugin from chris to ST2.
Maybe someone can help me, with the last small issues...
Have a look at my posting: http://www.sencha.com/forum/showthread.php?137632-mostly-working-pinch-zoom-image-carousel-help-perfect-it!&p=784858&viewfull=1#post784858 (http://www.sencha.com/forum/showthread.php?137632-mostly-working-pinch-zoom-image-carousel-help-perfect-it%21&p=784858&viewfull=1#post784858)

bhomass
26 Jul 2012, 3:06 PM
I still have problem with this class.

in general, you may not know the ratio of the image, so a good option is to specify the desired width and let the image size adjust the height by keeping the same ratio. this means when you call this PinchZoomImage class, you don't set the height.

however, if the initial height remains null, then the code breaks when you do zoom/pinch, because you are multiplying null by a fractional number.

any one knows a way to discover the image height after it has been painted?

bhomass
26 Jul 2012, 4:45 PM
I got it.

on load, I picked it up by
var height = e.element.dom.firstChild.height;

lucas.queiroz
13 Aug 2012, 1:08 PM
Hello,
I implemented the example cited in post#1(http://www.sencha.com/forum/showthread.php?187928-Pinch-Zoom-Scrollable-Image),


but could not perform the pinch with him (he simply does not detect the pinch), only the DoubleTap worked properly. I have


an android GalaxyII 2.3.3, anyone know if you have any restriction to enable the pinch or perhaps something in sencha? I'm


using sencha touch 2.0.1.
note: I did the same tests in IOS simulator with xCode, worked.

armode
14 Aug 2012, 11:07 PM
You can't track pinch gestures on Android 2.x, that's why we added zoom in/out Buttons to the pinch-plugin (http://www.sencha.com/forum/showthread.php?197903-Pinch-Image-with-carousel-and-working-fine&p=786652#post786652) from Chris.

in4p
21 Sep 2012, 3:29 PM
@mrsunshine

This is a great piece of code and very useful.

I ran into a few usability issues on my implementation:
1) If the user makes the image very small then the pinch to zoom can be difficult (as they have to pinch on the image) -> Easy fix by setting a minimum size
2) The resizing was a little 'wonky'. It always resized from the initial image size. This is odd, for example, once you have zoomed into the image and want to make it smaller, the decrease zoom factor should be applied to the enlarged version of the image, not the original version.

Anyways, to fix the above I added / modified the following, and others might be interested in doing the same.

To the prototype config added:

scaleWidth: 0

In the listeners in initImage added:

pinchstart: { element: 'element',
fn: this.onImagePinchStart
}

Implemented the pinchStart listener (had to account for some quirks on devices):

onImagePinchStart: function(e) { if(this.up('container').getScaleWidth()==0) {
this.up('container').setScaleWidth(this.getInitialConfig('width'));
}
else {
this.up('container').setScaleWidth(this.element.getWidth());
}
},

Modified the resizing method:

onImagePinch: function(e) { var initialWidth = this.getInitialConfig('width'),
initialHeight = this.getInitialConfig('height'),
imageRatio = initialWidth / initialHeight,
container = this,
image = this.element,
newWidth,
newHeight,
scroller = this.up('container').getScrollable().getScroller(),
pos = scroller.getMaxPosition();


newWidth = this.up('container').getScaleWidth() * e.scale;
newHeight = newWidth / imageRatio;

//Code for Min Size
if((newWidth < initialWidth) || (newHeight < initialHeight)) {
newWidth = initialWidth;
newHeight = initialHeight;
}


container.setWidth(newWidth);
container.setHeight(newHeight);
image.setWidth(newWidth);
image.setHeight(newHeight);


scroller.scrollTo(pos.x/2, pos.y/2);
},

You'll also note, that I'm doing part of the resizing by using the image ratio (to maintain proportions). The reason for this was that the rounding errors on converting the new sizes to integers had the potential to allow the image to get out of proportions (after multiple resizes).

Anyways, for any of you using @mrsunshine's code, I think the above smooth's the zooming out a bit.

BoomerBrian
4 Nov 2012, 12:49 PM
I am loading my images into a detail card from an html file using an ajax call so they are just plain html <img> tags.

I want to use this plugin but I am struggling trying to figure out how to get the <img> tag to an xtype of 'pinchzoomimage'

Does anyone have any suggestions?

Thanks.
Brian

in4p
4 Nov 2012, 1:11 PM
The following might work for you - in the 'success' return of your AJAX call, parse the img you return (pulling the src property) and then call the pinchzoomimage xtype, passing it the src you retrieved as the config parameter.

Alternatively, you can do roughly the same thing from within the 'pinchzoomimage' class, but you will have to modify some of the code of the class's internal code.


I am loading my images into a detail card from an html file using an ajax call so they are just plain html <img> tags.

I want to use this plugin but I am struggling trying to figure out how to get the <img> tag to an xtype of 'pinchzoomimage'

Does anyone have any suggestions?

Thanks.
Brian

Mike6679
12 Feb 2013, 12:46 PM
Great component. Thanks! I had to disable carousel swipes when scrolling. Add this to initImage()


this.add(image);

/*Disable carousel swipe if we are scrolling an image, Renable when scroll is complete */
var scroller = null;
scroller = image.up('container').getScrollable().getScroller(),
scroller.on("scrollstart",function(scrollerObject,offsetObject){
//debugger;
var carousel = this.up('carousel'),
element = carousel.element;


element.un({
dragstart : 'onDragStart',
drag : 'onDrag',
dragend : 'onDragEnd',
scope : carousel
});
});
scroller.on("scrollend",function(scrollerObject,offsetObject){
var carousel = this.up('carousel'),
element = carousel.element;


element.on({
dragstart : 'onDragStart',
drag : 'onDrag',
dragend : 'onDragEnd',
scope : carousel
});
});

jeffyt
12 Feb 2013, 1:16 PM
So I have tried to implement Post #1 into a Sencha Archtiect project, following is my generated code. I can fire a msgbox on Pinch and Double click but the image does not do anything.

app.html


<!DOCTYPE html>


<!-- Auto Generated with Sencha Architect -->
<!-- Modifications to this file will be overwritten. -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>pincher</title>
<script src="http://extjs.cachefly.net/touch/sencha-touch-2.1.0/sencha-touch-all-debug.js"></script>
<link rel="stylesheet" href="http://extjs.cachefly.net/touch/sencha-touch-2.1.0/resources/css/sencha-touch.css">
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript">
if (!Ext.browser.is.WebKit) {
alert("The current browser is unsupported.\n\nSupported browsers:\n" +
"Google Chrome\n" +
"Apple Safari\n" +
"Mobile Safari (iOS)\n" +
"Android Browser\n" +
"BlackBerry Browser"
);
}
</script>
</head>
<body></body>
</html>


app.js


*
* File: app.js
*
* This file was generated by Sencha Architect version 2.1.0.
* http://www.sencha.com/products/architect/
*
* This file requires use of the Sencha Touch 2.1.x library, under independent license.
* License of Sencha Architect does not include license for Sencha Touch 2.1.x. For more
* details see http://www.sencha.com/license or contact [email protected]
*
* This file will be auto-generated each and everytime you save your project.
*
* Do NOT hand edit this file.
*/


Ext.Loader.setConfig({
enabled: true
});


Ext.application({
views: [
'PinchZoomImage',
'container'
],
name: 'MyApp',


launch: function() {


Ext.create('MyApp.view.container', {fullscreen: true});
}


});


/app/view/MyView.js


/*
* File: app/view/MyImage.js
*
* This file was generated by Sencha Architect version 2.1.0.
* http://www.sencha.com/products/architect/
*
* This file requires use of the Sencha Touch 2.1.x library, under independent license.
* License of Sencha Architect does not include license for Sencha Touch 2.1.x. For more
* details see http://www.sencha.com/license or contact [email protected]
*
* This file will be auto-generated each and everytime you save your project.
*
* Do NOT hand edit this file.
*/


Ext.define('MyApp.view.MyImage', {
extend: 'Ext.Panel',


requires: [
'MyApp.view.PinchZoomImage'
],


config: {
fullscreen: false,
layout: {
type: 'hbox'
},
items: [
{
xtype: 'pinchzoomimage',
flex: 1,
src: 'http://upload.wikimedia.org/wikipedia/commons/5/5f/Super_Guppy_N941_NASA_landing.jpg'
}
]
}


});


/app/view/PinchZoomImage.js


/*
* File: app/view/PinchZoomImage.js
*
* This file was generated by Sencha Architect version 2.1.0.
* http://www.sencha.com/products/architect/
*
* This file requires use of the Sencha Touch 2.1.x library, under independent license.
* License of Sencha Architect does not include license for Sencha Touch 2.1.x. For more
* details see http://www.sencha.com/license or contact [email protected]
*
* This file will be auto-generated each and everytime you save your project.
*
* Do NOT hand edit this file.
*/


Ext.define('MyApp.view.PinchZoomImage', {
extend: 'Ext.Container',
alias: 'widget.pinchzoomimage',


config: {
src: '',
height: 'n',
width: 'n',
scrollable: true
},


initImage: function(newImageSrc) {
var height = this.getHeight() || this.element.getHeight(),
width = this.getWidth() || this.element.getWidth(),
src = this.getSrc() || newImageSrc,
image = null;


if (Ext.isString(src) && src !== '') {
image = Ext.create('Ext.Img', {
// set mode auf empty to create a real image tag
mode: '',
height: height,
width: width,
src: src,
listeners: {
pinch: {
element: 'element',
fn: this.onImagePinch




},
doubletap: {
element: 'element',
fn: this.onImageDoubletap
}
}
});




this.add(image);
}


console.log('initImage');
},


onImagePinch: function(e) {
var initialWidth = this.getInitialConfig('width'),
initialHeight = this.getInitialConfig('height'),
newWidth = initialWidth * e.scale,
newHeight = initialHeight * e.scale,
container = this,
image = this.element,
scroller = this.up('container').getScrollable().getScroller(),
pos = scroller.getMaxPosition();


container.setWidth(newWidth);
container.setHeight(newHeight);
image.setWidth(newWidth);
image.setHeight(newHeight);
scroller.scrollTo(pos.x/2, pos.y/2);
},


onImageDoubletap: function(e) {
var initialWidth = this.getInitialConfig('width'),
initialHeight = this.getInitialConfig('height'),
container = this,
image = this.element;








container.setWidth(initialWidth);
container.setHeight(initialHeight);
image.setWidth(initialWidth);
image.setHeight(initialHeight);


Ext.Msg.alert('DoubleTap');
},


applySrc: function(newImageSrc) {


var oldImage = this.down('img');




if (Ext.isObject(oldImage)) {
oldImage.destroy();
}




this.initImage(newImageSrc);


console.log('applySrc');
}


});

Mike6679
14 Feb 2013, 10:39 AM
Was anyone able to smooth the centering of the zoom??

evegraphic
29 May 2013, 2:18 AM
Hi everyone,

I tried what there is in first post but I see no image.
I've generated a new app in sencha touch 2.1 without changing anything.
I add a new item in the tab panel (view Main.js) :



{ title: 'Pinch',
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'Test pinch zoom image'
},
{
flex: 1,
xtype: 'pinchzoomimage',
src: 'resources/images/apercu-annonces.jpg'
}
]
}



The "pinchzoomimage" is in the DOM but i see nothing. Every element has "width: 0px !important" and "height: 0px !important".

I must add a width and a height to see image like the second example in the first post.



{ flex: 1,
xtype: 'pinchzoomimage2',
src: 'resources/images/apercu-annonces.jpg',
width: 800,
height: 500
}


What I do wrong ?

schaudhry123
2 Jul 2013, 10:26 AM
Hey,

This has worked beautifully for me except for that some of the images must be double tapped to appear. After that, they work as normal. Any way to fix this?