(function ( $ ) { $.fn.finepic = function( pid, options ){ var $this = this; $this.settings = $.extend({ host: "finepic.sk", thumbsWidth: 800, thumbsHeight: 600, defaultZoomBoxWidth:240, defaultZoomBoxHeight:200, startRotate: 0, boxCss: { cursor: 'w-resize' } }, options); $this.ready = false; $this.startRotate = $this.settings.startRotate;; $this.rotate = $this.startRotate; $this.init = function(){ // do not touch you stinky lil shit!!! var width = $this.get(0).clientWidth; var height = $this.get(0).clientHeight; $this.product.width = width; $this.product.height = height; $this.width = width; $this.height = height; if ( width > 0 && height >0 ){ $this.product.load( pid, width, height ); } return $this; }; // PRODUCT $this.product = new function(){ var product = this; this.pid = pid; this.total_frames = 90; this.load = function( pid, width, height ){ this.pid = pid; this.width = width; this.height = height; if (this.pid.length && this.width > 0 && this.height > 0){ this.loadData() } }; this.loadData = function(){ $.ajax({ url: 'https://ngn.' + $this.settings.host + '/?v=v2&pid=' + this.pid + '&w=' + this.width + '&h=' + this.height, dataType: 'json' }).done( function( product_data ){ $this.product.layers = product_data.layers; $this.product.total_frames = product_data.total_frames; $this.product.category_alias = product_data.category_alias; $this.product.manufacturer_alias = product_data.manufacturer_alias; $this.product.product_alias = product_data.product_alias; $this.product.frames = product_data.frames; $this.events.onLoadData( product_data ); }); return $this; }; }; //RENDERER $this.renderer = new function(){ var renderer = this; renderer.currentFrame = 0; renderer.hoverBack = true; renderer.loadedLayers = 0; this.applyCss = function( css ){ for (i in css){ $this.css( i, css[i] ); } }; this.prepareLayers = function(){ if ($this.product.layers.length > 0){ renderer.layers = []; for (i in $this.product.layers){ layer = $this.product.layers[i]; if (layer.url) { var img = $(""); img.load(function(e){ renderer.loadedLayers++; if (renderer.loadedLayers == $this.product.layers.length){ $this.events.onLoadedLayers(); } }); console.log(img); img.attr("src", layer.url); var layerBox = $("
"); layerBox.append(img); renderer.layers.push(img); } } } }; this.showCanvas = function(){ renderer.canvas.css({ opacity: 1 }); }; this.prepareViewBox = function(){ var holder = $("
"); var introFrame = $("
"); var canvas = $("
"); var progressBox = $("
"); var dragBox = $("
"); //css holder.css({ position: 'relative', overflow: 'hidden', width: $this.product.width, height: $this.product.height }); holder.addClass("holder"); introFrame.css({ width: $this.width, height: $this.height, position: 'absolute', top: '0', left: '0', background: 'url(https://thumb.'+$this.settings.host + '/prods/' + $this.product.category_alias + '/' + $this.product.manufacturer_alias + '/' + $this.product.product_alias + "/cropped/" + $this.width + "x" + $this.height + '/' + $this.product.frames[renderer.currentFrame] + ')' }); introFrame.addClass("introFrame"); canvas.css({ width: $this.width, height: $this.height, position: 'absolute', top: '0', left: '0', opacity: 0 }); canvas.addClass("canvas"); progressBox.css({ width: $this.width, height: $this.height, position: 'absolute', top: 0, left: 0, opacity: 1, background: "url('https://ngn." + $this.settings.host + "/res/progress.gif') 95% 5% no-repeat" }); progressBox.addClass("progressBox"); dragBox.css({ width: $this.width, height: $this.height, position: 'absolute', top: 0, left: 0, background: 'white', opacity: 0 }); dragBox.addClass("dragBox"); //appending $this.append(holder); holder.append(introFrame); holder.append(canvas); holder.append(progressBox); holder.append(dragBox); renderer.canvas = canvas; renderer.holder = holder; renderer.introFrame = introFrame; renderer.progressBox = progressBox; renderer.dragBox = dragBox; }; this.appendLayers = function(){ for ( i=0; i < renderer.layers.length; i++ ){ layer_img = renderer.layers[i]; renderer.canvas.append(layer_img); } }; this.setRotate = function( deg ){ $this.rotate = deg % 359; if ( $this.rotate < 0) $this.rotate += 359; frame_id = Math.round((($this.product.total_frames - 1) / 359) * $this.rotate); this.showFrame( frame_id ); }; this.showFrame = function( frame_id ){ renderer.currentFrame = frame_id; renderer.canvas.css({ left : (-$this.product.width * frame_id) }) }; this.animRotate = function( deg, time ){ if (!time) time = 250; $({rot: $this.rotate}).animate({rot: deg},{ duration: time, step: function(){ renderer.setRotate( this.rot ) } }); }; this.hideProgressBox = function(){ $this.renderer.progressBox.animate({opacity:0}, 400); }; // Static functions this.showStaticBox = function(){ var staticBox = $("
"); var holder = $("
"); staticBox.css({ width: $this.width, height: $this.height, position: 'absolute', top: '0', left: '0', background: 'url(https://thumb.'+$this.settings.host + '/prods/' + $this.product.category_alias + '/' + $this.product.manufacturer_alias + '/' + $this.product.product_alias + "/thumbs/" + $this.width + "x" + $this.height + '/' + $this.product.frames[renderer.currentFrame] + ') center center no-repeat' }); staticBox.addClass("staticBox"); //css holder.css({ position: 'relative', overflow: 'hidden', width: $this.product.width, height: $this.product.height }); holder.addClass("holder"); holder.append( staticBox ) $this.append( holder ); $this.renderer.staticBox = staticBox; }; return renderer; }; //ZOOM $this.zoom = function(){ var zoom = this; zoom.show = function(){ var current_frame = $this.renderer.currentFrame; var thumb_name = $this.product.frames[ current_frame ]; var width = $this.settings.thumbsWidth; var height = $this.settings.thumbsHeight; var product_alias = $this.product.product_alias; var category_alias = $this.product.category_alias; var manufacturer_alias = $this.product.manufacturer_alias; var thumb_uri = "https://thumb." + $this.settings.host + "/prods/" + category_alias + "/" + manufacturer_alias + "/" + product_alias + "/thumbs/" + width + "x" + height + "/" + thumb_name; zoom.showBox( thumb_uri ); }; zoom.getDimensions = function( img_width, img_height ){ var window_width = $(window).innerWidth() * 0.9; var window_height = $(window).innerHeight() * 0.9; var max_width = Math.min( img_width, window_width ); var max_height = Math.min( img_height, window_height ); var ratio = img_width / img_height; if (window_width / window_height > ratio ){ var width = max_height * ratio; var height = max_height; }else{ var width = max_width; var height = max_width / ratio; } return { width: Math.round(width), height: Math.round(height), top: Math.round(($(window).innerHeight() - height) / 2), left: Math.round(($(window).innerWidth() - width) / 2) } }; zoom.showBox = function( img_uri ){ var dimensions = zoom.getDimensions( $this.settings.defaultZoomBoxWidth, $this.settings.defaultZoomBoxHeight ); var overlay = $("
"); overlay.css({ position: 'fixed', width: '100%', height: '100%', top: '0', left: '0', background: '#000', opacity: '0', 'z-index': '9990' }); var box = $("
"); box.css( { 'position': 'fixed', 'left': dimensions.left, 'top': dimensions.top, 'min-width': $this.settings.defaultZoomBoxWidth, 'min-height': $this.settings.defaultZoomBoxHeight, 'padding': 3, 'z-index': '9991', 'opacity': 0, 'border-radius': '5px', 'background': 'white url("https://ngn.' + $this.settings.host + '/res/progress.gif")center center no-repeat', 'overflow': 'hidden' } ); var centerBox = $("
"); var tr = $(""); var td = $("").css({width: '100%', height: '100%', 'vertical-align': 'middle', 'padding': '0'}); tr.append(td); centerBox.append(tr).css({ background: 'white', 'border-radius': '3px' }); box.append(centerBox); $("body").append(overlay).append(box); //animated show overlay and zoombox box.animate({opacity:1}, 200); overlay.animate({opacity:0.4}, 100); $(overlay).mouseup(function(){ box.remove(); overlay.remove(); }); //Image - load and show var img = $("").attr( "src", img_uri ); img.one('load', function(){ // append image to box td.append( img ); zoom.imgRealWidth = img.width(); zoom.imgRealHeight = img.height(); img.css({ 'display': 'block', 'width': '100%' }); dimensions = zoom.getDimensions(img.width(), img.height() ); box.css({ 'left': dimensions.left, 'top': dimensions.top, 'width': dimensions.width, 'height': dimensions.height, 'min-height': '0', 'min-width': '0', 'background': 'white' }); //set resizing $(window).resize(function(){ dimensions = zoom.getDimensions( zoom.imgRealWidth, zoom.imgRealHeight ); box.css({ 'width': dimensions.width, 'left': dimensions.left, 'height': dimensions.height, 'top': dimensions.top }); }); }); }; return zoom; }; // EVENTS $this.events = new function(){ var events = this; events.pointer = { draging: false, x: 0, y:0 }; this.onLoadData = function( product_data ){ if ( product_data.status == 1 ){ $this.ready = true; $this.renderer.applyCss( $this.settings.boxCss ); $this.renderer.prepareViewBox(); $this.renderer.prepareLayers(); events.setEvents(); touchEvents = new $this.touchEvents(); touchEvents.setEvents(); } if ( product_data.status == 2 ){ $this.renderer.showStaticBox(); } }; this.onLoadFx = function(){ $this.fx.init(); }; this.onMouseOverFx = function(){ $this.fx.pause(true); if (!window.finePicDraging && $this.renderer.hoverBack){ $this.renderer.animRotate( $this.rotate - 25, 100 ); } }; this.onMouseOutFx = function(){ if (!window.finePicDraging && $this.renderer.hoverBack){ $this.renderer.animRotate( $this.rotate + 25 , 100 ) $this.fx.pause(false); } }; $this.onClick = function(e){ $this.zoom().show(); }; this.onMouseDown = function(e){ events.lastRotation = $this.rotate; }; this.onMouseUp = function(e){ }; this.onLoadedLayers = function(){ $this.renderer.appendLayers(); $this.renderer.showCanvas(); $this.renderer.hideProgressBox(); events.onLoadFx(); }; this.onDrag = function(e){ $this.renderer.setRotate(events.lastRotation - events.pointer.x); }; this.setEvents = function(){ // handle hover $this.renderer.dragBox.hover(function(){ events.onMouseOverFx(); }, function(){ events.onMouseOutFx(); }); // handle dragging $this.renderer.dragBox.mousedown(function(e){ e.preventDefault(); events.pointer.startX = e.pageX; events.pointer.startY = e.pageY; events.pointer.d = 0; events.onMouseDown(e); $(document).bind("mousemove",function(e){ e.preventDefault(); e.stopPropagation(); window.finePicDraging = true; events.pointer.x = e.pageX - events.pointer.startX; events.pointer.y = e.pageY - events.pointer.startY; events.pointer.d = Math.sqrt((events.pointer.x * events.pointer.x) + (events.pointer.y * events.pointer.y)); events.onDrag(e); }) }); $this.renderer.dragBox.mouseup(function(e){ e.preventDefault(); if (events.pointer.d < 2) { $this.onClick(e); } events.onMouseUp(e); }); $(document).mouseup(function(e){ e.preventDefault(); e.stopPropagation(); if (events.pointer.d >= 2) { $this.renderer.hoverBack = false; } $(document).unbind("mousemove"); window.finePicDraging = false; }); } }; //TOUCH EVENTS $this.touchEvents = function(){ var touchEvents = this; touchEvents.startX = false; touchEvents.startY = false; touchEvents.dX = 0; touchEvents.dY = 0; touchEvents.startRotate = 0; touchEvents.setEvents = function(){ $this.renderer.dragBox.bind("touchstart", touchEvents.touchStart); $this.renderer.dragBox.bind("touchend", touchEvents.touchEnd); $this.renderer.dragBox.bind("touchmove", touchEvents.touchMove); $this.renderer.dragBox.bind("touchCancel", touchEvents.touchCancel); $this.renderer.dragBox.bind("touchLeave", touchEvents.touchLeave); }; touchEvents.touchStart = function(e){ e = e.originalEvent; e.preventDefault(); e.stopPropagation(); touchEvents.startX = e.touches[0].pageX; touchEvents.startY = e.touches[0].pageY; touchEvents.startRotate = $this.rotate; }; touchEvents.touchEnd = function(e){ e = e.originalEvent; e.preventDefault(); e.stopPropagation(); if (Math.sqrt((touchEvents.dX * touchEvents.dX) + (touchEvents.dY * touchEvents.dY)) < 10){ $this.zoom().show(); } touchEvents.dX = 0; touchEvents.dY = 0; }; touchEvents.touchMove = function(e){ e = e.originalEvent; e.preventDefault(); e.stopPropagation(); touch = e.touches[0]; touchEvents.dX = touch.pageX - touchEvents.startX; touchEvents.dY = touch.pageY - touchEvents.startY; rotate = touchEvents.startRotate - Math.round(touchEvents.dX / 1.5); $this.renderer.setRotate( rotate ); }; touchEvents.touchCancel = function(e){ e = e.originalEvent; e.preventDefault(); e.stopPropagation(); }; touchEvents.touchLeave = function(e){ e = e.originalEvent; e.preventDefault(); e.stopPropagation(); }; return touchEvents; }; $this.fx = new function(){ var fx = this; fx.allowed = true; fx.defaults = { autoRotate:{ speed: 100, direction : 1 }, autoSwing: { speed: 50, direction: 1 } }; fx.init = function(){ $this.renderer.animRotate( $this.startRotate - 35); if ($this.settings.autoRotate){ fx.autoRotate(); } if ($this.settings.autoSwing){ fx.autoSwing(); } }; fx.pause = function( stop ){ fx.allowed = !stop; }; fx.autoRotate = function(){ fx.autoRotate.speed = $this.settings.autoRotate.speed ? $this.settings.autoRotate.speed : fx.defaults.autoRotate.speed; fx.autoRotate.direction = $this.settings.autoRotate.direction ? $this.settings.autoRotate.direction : fx.defaults.autoRotate.direction; this.interval = setInterval(function(){ if (fx.allowed){ $this.renderer.setRotate( $this.rotate + fx.autoRotate.direction ); } }, 1000 / fx.autoRotate.speed); }; fx.autoSwing = function(){ fx.autoSwing.index = 0; fx.autoSwing.speed = $this.settings.autoSwing.speed ? $this.settings.autoSwing.speed : fx.defaults.autoSwing.speed; fx.autoSwing.direction = $this.settings.autoSwing.direction ? $this.settings.autoSwing.direction : fx.defaults.autoSwing.direction; this.interval = setInterval(function(){ if (fx.allowed){ fx.autoSwing.index = (fx.autoSwing.index + fx.autoSwing.direction) % 360; offset = Math.sin( fx.autoSwing.index * Math.PI / 180 ); $this.renderer.setRotate( $this.rotate + offset ); } }, 1000 / fx.autoSwing.speed); }; }; $this.init(); return $this; }; }( jQuery ));