News

Create touch responsive web content

Enhance the touch experience for mobile devices and help recreate the native app experience

step21

You may think that making websites responsive to touchscreen devices is a bit redundant, given that these devices can interact with most of the standard website functionality found online. That is true, but as this market continues to expand we can take advantage of the unique input that is on offer through such devices, and give an enhanced experience for those specific users.

In this tutorial we are going to offer the kind of functionality to our web content that you are more likely to find inside a native app. We are going to take three div tags and give them the functionality of letting the user drag them around the screen (which has been possible on the desktop for quite some time). But, we’re taking this one step further – we will allow a pinch gesture to scale the content up and down. Not only that, but we’ll take the rotation of the two fingers and apply that to the div as well. Applying this to the div might seem a little odd, but add images to those divs and you have a sortable photo stack, just like you see on those BBC spy dramas! Web Designer will not take any responsibility for you sitting in a darkened room using the contents of this tutorial to brief your minions.

DOWNLOAD TUTORIAL FILES

Getting started

Copy the start folder over to your computer from the resource disc and launch Dreamweaver or a similar code editor. Create a new html page and in the head section of the code add the meta tag, as shown, for the viewport to stop scaling on mobile devices – then we’ll add a link to the jQuery library as well.

001 <meta name=”viewport”  content=”width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;”>
002 <script src=”https://ajax.googleapis.com/  ajax/libs/jquery/1.7.2/jquery.min.js”></script>

Setting content

Move down into the main body tags of your document now, and we’ll add the code shown here. First and foremost we want some instructions for our site visitors, so the paragraph will take care of that for us. Next we add a div tag that contains a unique id and a more generic class, which will help us with functionality later.

001 <p> Touch to move, pinch to scale and rotate</p>
002 <div id=”move1″>
003 </div>

Finish the content

We add two more div tags to our page now, so this will generate three thumbnail photos on the document. These will be able to be scaled, rotated and moved later. The ids enable the addition of a separate image into the background using CSS so that there is a unique look to each of these div tags.

001 <div id=”move2″>
002 </div>
003 <div id=”move3″>
004 </div>

Setting the page style

We’ll move back up to the top of the document now and into the head section of the code again. Add the opening style tag as shown followed by the styling for the body. This makes the background fullscreen by setting the height and min-height to 100%, but sometimes scrollbars are added, so set the overflow to hidden to prevent this.

001 <style>
002
003 body {
004     height: 100%; min-height: 100%;
005     overflow: hidden;
006     background-image: url(images/bg.jpg);
007     background-size: 100%;
008 }

Style the instructions

The next style element that we are going to make is the instructions. Here, we make the colour of the text similar to the colour in the background image, and we set the size of the type and add a 4px drop shadow to add definition. There is no offset on either the x or the y axes, so the shadow will just sit behind the text with 70% Opacity.

001 .inst {
002     color: #efdfe4;
003     font-size: 1.6em;
004     text-shadow: 0 0 4px rgba(0,0,0,0.7);
005 }

Add the photo

We are now going to add the styling for the first photo. We position this absolutely so we can then move it to any position on the display later, to coincide with our touch move. Once we’ve gone and set its position to 50px in from the left and 100px down from the top, we add the image and make it fill the size of the div.

001 #move1 {position: absolute; top:100px; left:50px;
002     background-image:url(images/golden.jpg);
003     background-size:100%;}

Second photo style

The next photo style is pretty similar to the first. Notice that we are again positioning it 100px down from the top but are moving it to 300px in from the left. Each image will be a standard square of 200px in width and height, so this allows for 50px spacing between each of the images on the display.

001  #move2 {position: absolute; top:100px; left:300px;
002     background-image:url(images/london.jpg);
003     background-size:100%;}

The final image

We now add the final styling code for the unique properties of the images. Again, we’ve moved it further along the display at 550px to give us that extra bit of spacing, and we’ve added a brand new, different image in the background. All three of the images contain similar styling – this will be handled by the photo class in the next step, in order to keep the CSS for each to a minimum.

001  #move3 {position: absolute; top:100px;    left:550px;
002     background-image:url(images/durdle.jpg);
003     background-size:100%;}

Borders and shadows

Each of the images have some similar properties to them, so these are added as the photo class. We make the border and size the same, but we also add a drop shadow. Despite the fact that the Chrome browser on Android is a WebKit browser, it doesn’t take the WebKit prefix for the shadow. This shadow will help give definition to the images.

001  .photo {
002     width: 200px; height: 200px;
003     border: 5px solid #eee;
004     border-width:7px 7px 20px 7px;
005     -WebKit-box-shadow:    0px 2px 15px #333;
006     box-shadow:    0px 2px 15px #333;
007 }
009 </style>

Set the script area

Save the page and test it in a browser to make sure the three images work. We are going to add the script section in the body tags of the page, just before the final closing body tag. Note we have a script section defined and a jQuery document-ready short hand function. Our code will be added where the comment is.

001  <script type=”text/javascript”>
002 function ($) {
003 //code will go here
004 }(jQuery));
005 </script>

Detect touch move

Add the following – it binds the touchmove event with any div that contains the photo class. The touchmove isn’t an event recognized by default in jQuery, hence binding it. We then detect that the display is touched and grab the x and y location but half the width of the photos, which are 200 x 200px.

001  $(“.photo”).bind(“touchmove”, function(e) { 
002      var targetEvent = e.originalEvent.      touches[0] || e.originalEvent. changedTouches[0];
003      var tempX = targetEvent.clientX-100;
004      var tempY = targetEvent.clientY-100;

Finish the touchmove

Once we have the x and y location we need to move the appropriate div to that position. Add the css properties for the left and top position to the selected photo image. The ‘prevent default’ code stops the page from being scrolled as the user moves their finger around the screen. Save and test your page on a device.

001 $(this).css({‘left’ : + tempX + ‘px’, ‘top’ : + tempY + ‘px’ });
002 e.preventDefault();
003 return false;
004 });

Defining the touchstart

After testing, one problem is that as you move one image over another, the page’s stacking order is retained. We can change that by lifting the z-index order when the user initially touches the screen. This code makes the selected photo appear above the others on the page. Again, save this and test it on your device.

001 $(“.photo”).bind(“touchstart”, function(e) {
002 e.preventDefault(); 
003 $(this).css({‘z-index’ : ‘500’ });
004 return false; 
005 });

Letting go of the photo

The last code lifts an image while pressed, but once all of the images have been touched, the same problem still exists, in that the last image selected is not the top-most image on the page. As part of the solution, let’s add the next section of code for when a user takes their finger off of the display. This then changes the z-index back to 100. It’s still not fixed but it’s the first part of the solution.

001 $(“.photo”).bind(“touchend”, function(e) { 
002 e.preventDefault(); 
003 $(this).css({‘z-index’ : ‘100’ });
004 return false; 005 });

Define some variables

We are going to have a z-index value set in memory for each of the photos. This could just as easily be saved in an array if you are going to have a larger number of photos, but in this instance having a separate variable for each will suffice. Place these just after the JavaScript opening tag in the document.

001 var z1 = 100, z2 = 100, z3 = 100;
002 var scale = 1;

Change the depths

Go back to the touchend function and remove the css line, as this is not required now. Instead add the code as shown. This detects whether the photo being released by the finger is the move1 div tag. If so, it is set to have a value of 100, while the remaining two z values are set below this.

001 if (e.target.id == “move1”)
002 {
003 z1 = 100;
004 z2 –;
005 z3 –;
006 }

Continuing the concept

Add the next section of code that builds on the last section, again identifying the move2 div container and setting the z value to 100. If the first had been selected prior to this, then the z order would place the third photo at the bottom, then the first and this second one would be at the top of the order.

001 if (e.target.id == “move2”)
002 {
003 z1 –;
004 z2 = 100;
005 z3 –;
006 }

Last order sorted

Now we add the if statement for the last of our three photo div tags. It’s interesting to note that
e.target.id is the same as the jQuery command $(this). The e.target.id is regular JavaScript that takes the event, then the target of that event, and grabs the actual id name. It’s always useful to know both!

001 if (e.target.id == “move3”){
002 z1 –;
003 z2 –;
004 z3 = 100;
005 }

Set the z-index

As we have sorted whichever photo has been selected, we now write the values of the z variables into the z-index CSS property with the next block of code. Remember this should be inside the touchend function. Save this and give it a test; you will have self-sorting images, with the last selected always on top of the display stack.

001 $(‘#move1’).css({‘z-index’ : + z1 });
002 $(‘#move2’).css({‘z-index’ : + z2 });
003 $(‘#move3’).css({‘z-index’ : + z3 });

Library link up

We’re going to detect the scaling and rotation of two fingers on the photo. In order to do that, we need to get access to those specific properties. This is easy in iOS, but not so easy on Android or Playbook, so we are going to link to the hammer.js library. Add the two lines shown in the head section of the document.

001 < script src=”hammer.js”>< /script>
002 < script src=”jquery.specialevent.hammer.js”>< /script>

The transform event

The next section of code should be added after the touchend function. This saves the photo class into a variable and applies the transform function to every instance of that class. In this code we are just stopping the regular event propagation of moving the screen, which if pinched would zoom.

001 var $ph = $(‘.photo’);
002 $ph.on(‘transform’, function (event) {
003 event.preventDefault();

Scale and rotate

The transform function automatically gives access to rotation and scale; as such we can simply write those factors into the CSS. We use the event prefix to get access to both the scale and rotate. The WebKit transform CSS3 property sets the values. Save this and test the final project. You should ideally test it on a tablet device such as an iPad or Android tablet, so you can get to grips with the functions when using a slightly larger touchscreen than a smartphone.

001 $(this).css({‘-WebKit-transform’ : ‘rotate(‘ + event.rotation + ‘deg)’ + ‘scale(‘ + event.scale*scale +
002 ‘)’});
003 });

GESTURE ON iOS


Detecting gestures such as pinch and zoom is very simple to do on iOS devices because they have the JavaScript events ongesturestart, ongesture and ongestureend. These bring back properties such as rotate and scale very easily, ready to manipulate the DOM with. However, if you take a document using these events onto Android or Blackberry then quite simply there is absolutely no response. The W3C has specified touchstart, touchend, touchmove, touchenter, touchleave, and touchcancel as valid event types. As you can see the gesture event is not valid, and that’s why it doesn’t work as a cross-browser solution. In order to get this working across different devices, we have used the hammer.js framework (as in MC Hammer of Can’t Touch This fame), from eightmedia.GitHub.com/hammer.js.

×