This blog shows you how to create a portlet to be able to zoom in and out of an image. This portlet is web content driven using Liferay 6.2, jquery and animate.css. I have included all the source code for this project at the bottom of this page.
How it Looks:
When you first bring up the portlet, you see an image in a scrollbar with various points defined. The scrollbar is required & important. The points are defined using x & y coordinates, so to ensure they always point to the same location on the image, the image is not resizable. If this is viewed in on a mobile device, the scrollbar will appear with points pointing to the same spot on the image.
After you click on a point, you’ll see more details, as shown below. To close the image, click ‘close’ and the portlet zooms back to the original image.
Technical Details
- This portlet uses animate.css to animate the images as they float into the viewport.
- The Java portlet code basically does the following:
- Looks up the web content using a specified tag.
- Pulls the required values out of the web content, using the Liferay XML parsing API.
- Instantiates a zoomable class and puts it into the request.
Structure:
The Web Content structure contains the following fields:
- Title
- MainImage
- Repeatable Points, including
- Title
- Description
- Image
- X coordinate
- Y coordinate
The src for this structure is also in the ZoomableStructure.xml file inside the zip file at the bottom of this page.
Java Portlet Code
JournalArticle wc = JournoalArticleLocalServiceUtil.getArticle(groupId, String.valueOf(ae.getClassPK() - 2)); Document journalDoc = SAXReaderUtil.read(wc.getContentByLocale(themeDisplay.getLocale().toString())); Document titleDoc = SAXReaderUtil.read(wc.getTitle());Node mainImageNode = journalDoc.selectSingleNode(String.format("root/dynamic-element[@name='%1$s']/dynamic-content[@language-id='%2$s']", "mainImage", locale)); Node mainTitleNode = titleDoc.selectSingleNode(String.format("//Title[@language-id='%1$s']", locale)); z = new Zoomable(mainTitleNode.getText(), mainImageNode.getText()); Node root = journalDoc.getRootElement(); List<Node> pointNodes = root.selectNodes("/root/dynamic-element[@name='pointEnabled']"); ZoomPoint point; for (int i = 0; i < pointNodes.size(); i++) { Node pointNode = pointNodes.get(i); Node enabledNode = pointNode.selectSingleNode(String.format("dynamic-content[@language-id='%1$s'][last()]",locale)); Node titleNode = pointNode.selectSingleNode(String.format("dynamic-element[@name='%1$s']/dynamic-content[@language-id='%2$s']", "title", locale)); if (Boolean.valueOf(enabledNode.getText())) { Node descNode = pointNode.selectSingleNode(String.format("dynamic-element[@name='%1$s']/dynamic-content[@language-id='%2$s']", "description", locale)); Node imageNode = pointNode.selectSingleNode(String.format("dynamic-element[@name='%1$s']/dynamic-content[@language-id='%2$s']", "image", locale)); Node xNode = pointNode.selectSingleNode(String.format("dynamic-element[@name='%1$s']/dynamic-content[@language-id='%2$s']", "x", locale)); Node yNode = pointNode.selectSingleNode(String.format("dynamic-element[@name='%1$s']/dynamic-content[@language-id='%2$s']", "y", locale)); z.addPoint(titleNode.getText(),descNode.getText(),imageNode.getText(),Integer.valueOf(xNode.getText()),Integer.valueOf(yNode.getText())); } }
JSP snippet:
<div> <div class="carousel-container animated fadeIn" style="overflow:auto"> <div class="row-fluid"> <div class="span10"> <h3 class="outside-text"> Zoom to see Details: <c:out value='${requestScope.zoomable.title}'/> </h3> </div> </div> <div class="row-fluid options" > <div class="main-module animated slideInRight"> <div class="tooltips animated bounceInDown"> <c:forEach var="point" items="${requestScope.zoomable.points}"> <div id="point3" class="rotate point modulePoint" data-img="<c:out value='${point.image}'/>" data-title="<c:out value='${point.title}'/>" data-desc="<c:out value='${point.desc}'/>" style="top:<c:out value='${point.y}'/>px;left: <c:out value='${point.x}'/>px;" onClick="var image = $(this).attr('data-img'); $('.main-module > img').animate({zoom:1.3, opacity:0.0 }, 500); $('.tooltips').toggle(); $('.zoomImage > img').attr('src', image); $('.zoom-module').css({display: 'block'}); $('.zoom-module').show(); $('#zoomTitle').html($(this).attr('data-title')); $('.zoomOutClose').show(); $('#zoomDesc').html($(this).attr('data-desc'));"> <i class="fa fa-search-plus"></i> </div> </c:forEach> </div> <image src="<c:out value='${requestScope.zoomable.mainImage}'/>" /> </div> </div> <div class="zoom-module"> <div onClick="var points = $('.tooltips'); var zoomModule = $('.zoom-module'); zoomModule.addClass('fadeOut'); $('.main-module > img').animate({zoom:1, opacity:1.0}, 500); zoomModule.removeClass('animated fadeIn'); zoomModule.css({display: 'none'}); points.toggle();" id="zoomOut" class="close"> <span class="smalltext">Close<i class="fa fa-search-minus"></i></span> </div> <div class="row-fluid"> <div class="zoomText animated fadeIn span6"> <h2 id="zoomTitle"></h2> <p id="zoomDesc"></p> </div> <div class="zoomImage animated slideInRight span6"> <img src="" style=""> </div> </div> </div> </div> </div>
Src code
Download ZoomIn-portlet src code.