Joomla Image Comparison Slider Plugin

Simply put, it's just an image comparison plugin for Joomla. After installing it, you need to enable it on plugin manager (Content - JMP Image Comparison Slider).

Image Comparison Slider Demo Forum

It works with Joomla 2.5+, 3 and 4.

Then go to The Article or Custom Module and add the syntax below:

{ics data-before="URL of first image" data-after="URL of second image" data-before-text="Custom text for first image (Optional)" data-after-text="Custom text for second image (Optional)" }

-------

Example:

{ics data-before="image/pic1.jpeg" data-after="image/pic2.jpeg" data-before-text="Old" data-after-text="New" }

-------

List files:

  • assets
  • jmpics.php
  • jmpics.xml

 

File: script.js

(function($){
	$(document).ready(function(){
		$('.jmpics').each(function(){
			let el=$(this), h='';

			if(typeof el.attr('data-before')=='undefined' || typeof el.attr('data-after')=='undefined') return;

			h='<figure class="cd-image-container">';
				h+='<img src="'+el.attr('data-before')+'" alt="">';
				if(typeof el.attr('data-before-text')!='undefined')
					h+='<span class="cd-image-label" data-type="original">'+el.attr('data-before-text')+'</span>';

				h+='<div class="cd-resize-img">';
					h+='<img src="'+el.attr('data-after')+'" alt="">';
					if(typeof el.attr('data-after-text')!='undefined')
						h+='<span class="cd-image-label" data-type="modified">'+el.attr('data-after-text')+'</span>';
				h+='</div>';
				h+='<span class="cd-handle"></span>';
			h+='</figure>';

			el.replaceWith(h);
		});

		// ics
		var dragging = false,
        scrolling = false,
        resizing = false;
	    
	    //cache jQuery objects
	    var imageComparisonContainers = $('.cd-image-container');
	    
	    //check if the .cd-image-container is in the viewport 
	    //if yes, animate it
	    checkPosition(imageComparisonContainers);
	    $(window).on('scroll', function(){
	        if( !scrolling) {
	            scrolling =  true;
	            ( !window.requestAnimationFrame )
	                ? setTimeout(function(){checkPosition(imageComparisonContainers);}, 100)
	                : requestAnimationFrame(function(){checkPosition(imageComparisonContainers);});
	        }
	    });
	    
	    //make the .cd-handle element draggable and modify .cd-resize-img width according to its position
	    imageComparisonContainers.each(function(){
	        var actual = $(this);
	        drags(actual.find('.cd-handle'), actual.find('.cd-resize-img'), actual, actual.find('.cd-image-label[data-type="original"]'), actual.find('.cd-image-label[data-type="modified"]'));
	    });

	    //upadate images label visibility
	    $(window).on('resize', function(){
	        if( !resizing) {
	            resizing =  true;
	            ( !window.requestAnimationFrame )
	                ? setTimeout(function(){checkLabel(imageComparisonContainers);}, 100)
	                : requestAnimationFrame(function(){checkLabel(imageComparisonContainers);});
	        }
	    });

	    function checkPosition(container) {
	        container.each(function(){
	            var actualContainer = $(this);
	            if( $(window).scrollTop() + $(window).height()*0.5 > actualContainer.offset().top) {
	                actualContainer.addClass('is-visible');
	            }
	        });

	        scrolling = false;
	    }

	    function checkLabel(container) {
	        container.each(function(){
	            var actual = $(this);
	            updateLabel(actual.find('.cd-image-label[data-type="modified"]'), actual.find('.cd-resize-img'), 'left');
	            updateLabel(actual.find('.cd-image-label[data-type="original"]'), actual.find('.cd-resize-img'), 'right');
	        });

	        resizing = false;
	    }

	    //draggable funtionality - credits to http://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/
	    function drags(dragElement, resizeElement, container, labelContainer, labelResizeElement) {
	        dragElement.on("mousedown vmousedown", function(e) {
	            dragElement.addClass('draggable');
	            resizeElement.addClass('resizable');

	            var dragWidth = dragElement.outerWidth(),
	                xPosition = dragElement.offset().left + dragWidth - e.pageX,
	                containerOffset = container.offset().left,
	                containerWidth = container.outerWidth(),
	                minLeft = containerOffset + 10,
	                maxLeft = containerOffset + containerWidth - dragWidth - 10;
	            
	            dragElement.parents().on("mousemove vmousemove", function(e) {
	                if( !dragging) {
	                    dragging =  true;
	                    ( !window.requestAnimationFrame )
	                        ? setTimeout(function(){animateDraggedHandle(e, xPosition, dragWidth, minLeft, maxLeft, containerOffset, containerWidth, resizeElement, labelContainer, labelResizeElement);}, 100)
	                        : requestAnimationFrame(function(){animateDraggedHandle(e, xPosition, dragWidth, minLeft, maxLeft, containerOffset, containerWidth, resizeElement, labelContainer, labelResizeElement);});
	                }
	            }).on("mouseup vmouseup", function(e){
	                dragElement.removeClass('draggable');
	                resizeElement.removeClass('resizable');
	            });
	            e.preventDefault();
	        }).on("mouseup vmouseup", function(e) {
	            dragElement.removeClass('draggable');
	            resizeElement.removeClass('resizable');
	        });
	    }

	    function animateDraggedHandle(e, xPosition, dragWidth, minLeft, maxLeft, containerOffset, containerWidth, resizeElement, labelContainer, labelResizeElement) {
	        var leftValue = e.pageX + xPosition - dragWidth;   
	        //constrain the draggable element to move inside his container
	        if(leftValue < minLeft ) {
	            leftValue = minLeft;
	        } else if ( leftValue > maxLeft) {
	            leftValue = maxLeft;
	        }

	        var widthValue = (leftValue + dragWidth/2 - containerOffset)*100/containerWidth+'%';
	        
	        $('.draggable').css('left', widthValue).on("mouseup vmouseup", function() {
	            $(this).removeClass('draggable');
	            resizeElement.removeClass('resizable');
	        });

	        $('.resizable').css('width', widthValue); 

	        updateLabel(labelResizeElement, resizeElement, 'left');
	        updateLabel(labelContainer, resizeElement, 'right');
	        dragging =  false;
	    }

	    function updateLabel(label, resizeElement, position) {
	        if(position == 'left') {
	            ( label.offset().left + label.outerWidth() < resizeElement.offset().left + resizeElement.outerWidth() ) ? label.removeClass('is-hidden') : label.addClass('is-hidden') ;
	        } else {
	            ( label.offset().left > resizeElement.offset().left + resizeElement.outerWidth() ) ? label.removeClass('is-hidden') : label.addClass('is-hidden') ;
	        }
	    }
	});
})(jQuery);

 

File: style.css

.hidden{display:none!important}
.cd-image-container{position:relative;display:inline-block;max-width:768px;margin:0 auto}
.cd-image-container img{display:block}
.cd-image-label{position:absolute;bottom:0;right:0;color:#fff;padding:1em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;opacity:0;-webkit-transform:translateY(20px);-moz-transform:translateY(20px);-ms-transform:translateY(20px);-o-transform:translateY(20px);transform:translateY(20px);-webkit-transition:-webkit-transform .3s 0.7s,opacity .3s .7s;-moz-transition:-moz-transform .3s 0.7s,opacity .3s .7s;transition:transform .3s 0.7s,opacity .3s .7s}
.cd-image-label.is-hidden{visibility:hidden}
.is-visible .cd-image-label{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}
.cd-resize-img{position:absolute;top:0;left:0;width:0;height:100%;overflow:hidden;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden}
.cd-resize-img img{position:absolute;left:0;top:0;display:block;height:100%;width:auto;max-width:none}
.cd-resize-img .cd-image-label{right:auto;left:0}
.is-visible .cd-resize-img{width:50%;-webkit-animation:cd-bounce-in .7s;-moz-animation:cd-bounce-in .7s;animation:cd-bounce-in .7s}
@-webkit-keyframes cd-bounce-in {
0%{width:0}
60%{width:55%}
100%{width:50%}
}
@-moz-keyframes cd-bounce-in {
0%{width:0}
60%{width:55%}
100%{width:50%}
}
@keyframes cd-bounce-in {
0%{width:0}
60%{width:55%}
100%{width:50%}
}
.cd-handle{position:absolute;height:44px;width:44px;left:50%;top:50%;margin-left:-22px;margin-top:-22px;border-radius:50%;background:#dc717d url(cd-arrows.svg) no-repeat center center;cursor:move;box-shadow:0 0 0 6px rgba(0,0,0,0.2),0 0 10px rgba(0,0,0,0.6),inset 0 1px 0 rgba(255,255,255,0.3);opacity:0;-webkit-transform:translate3d(0,0,0) scale(0);-moz-transform:translate3d(0,0,0) scale(0);-ms-transform:translate3d(0,0,0) scale(0);-o-transform:translate3d(0,0,0) scale(0);transform:translate3d(0,0,0) scale(0)}
.cd-handle.draggable{background-color:#445b7c}
.is-visible .cd-handle{opacity:1;-webkit-transform:translate3d(0,0,0) scale(1);-moz-transform:translate3d(0,0,0) scale(1);-ms-transform:translate3d(0,0,0) scale(1);-o-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1);-webkit-transition:-webkit-transform .3s 0.7s,opacity 0 .7s;-moz-transition:-moz-transform .3s 0.7s,opacity 0 .7s;transition:transform .3s 0.7s,opacity 0 .7s}

-------

Please share it if you find it useful. The article is referenced from the CodyHouse.

You may also like

Best Free Joomla 4 Templates of 2022

Joomla Modal & Popup Extension

JoomHelper Media Plugin

Say something here...
You are a guest ( Sign Up ? )
or post as a guest
People in conversation:
Loading comment... The comment will be refreshed after 00:00.
  • This commment is unpublished.
    Carsten · 1 months ago
    Hi guys I like the plugin but it does not work with Joomla 4.23 and PHP 8.0. I was activate the plugin and droped the code for two pictures in a text

    {ics data-before="/images/beforeafterimagesslide/freisteller-service-haare.jpg" data-after="/images/beforeafterimagesslide/bilder-freistellen-transparent.jpg"}

    But unfortunately nothing appears... any ideas?

    Thanks

    Carsten
    • This commment is unpublished.
      David · 1 months ago
      @Carsten Hi,
      I used the code you provided, replaced it with my pictures and checked on Joomla the latest version, it still works. Can you let me know the website address where you put this plugin?
  • This commment is unpublished.
    mic · 4 months ago
    doesn't work on my

    Joomla! 3.10.10 Stable [ Daraja ] 18-June-2022 16:32 GMT
    • This commment is unpublished.
      mic · 4 months ago
      @mic FYI: Debug Errors shown in Console

      imagecomparision:69 Uncaught TypeError: $(...).find(...).tooltip is not a function
      at initTooltips (imagecomparision:69:194)
      at HTMLDocument.<anonymous> (imagecomparision:69:21)
      at u (jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2:27579)
      at Object.fireWith [as resolveWith] (jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2:28337)
      at Function.ready (jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2:30124)
      at HTMLDocument._ (jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2:27307)
      initTooltips @ imagecomparision:69
      (anonymous) @ imagecomparision:69
      u @ jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2
      fireWith @ jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2
      ready @ jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2
      _ @ jquery.min.js?ad48fcf4eded40f912920a955f1065d5:2
    • This commment is unpublished.
      mic · 4 months ago
      @mic works now. needs a Slash before "image..."

Powered By JLex Comment.