metro4
Version:
The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style
254 lines (207 loc) • 9.29 kB
JavaScript
/* global Metro */
(function(Metro, $) {
'use strict';
var Utils = Metro.utils;
var ImageMagnifierDefaultConfig = {
imagemagnifierDeferred: 0,
width: "100%",
height: "auto",
lensSize: 100,
lensType: "square", // square, circle
magnifierZoom: 2,
magnifierMode: "glass", // glass, zoom
magnifierZoomElement: null,
clsMagnifier: "",
clsLens: "",
clsZoom: "",
onMagnifierMove: Metro.noop,
onImageMagnifierCreate: Metro.noop
};
Metro.imageMagnifierSetup = function (options) {
ImageMagnifierDefaultConfig = $.extend({}, ImageMagnifierDefaultConfig, options);
};
if (typeof window["metroImageMagnifierSetup"] !== undefined) {
Metro.imageMagnifierSetup(window["metroImageMagnifierSetup"]);
}
Metro.Component('image-magnifier', {
init: function( options, elem ) {
this._super(elem, options, ImageMagnifierDefaultConfig, {
zoomElement: null,
id: Utils.elementId("image-magnifier")
});
return this;
},
_create: function(){
var element = this.element;
this._createStructure();
this._createEvents();
this._fireEvent("image-magnifier-create", {
element: element
});
},
_createStructure: function(){
var element = this.element, o = this.options;
var magnifier, element_width, element_height;
var image = element.find("img");
if (image.length === 0) {
throw new Error("Image not defined");
}
if (!Utils.isValue(element.attr("id"))) {
element.attr("id", Utils.elementId("image-magnifier"));
}
element.addClass("image-magnifier").css({
width: o.width
}).addClass(o.clsMagnifier);
element_width = element.width();
switch (o.height) {
case "16/9": element_height = Utils.aspectRatioH(element_width, o.height); break;
case "21/9": element_height = Utils.aspectRatioH(element_width, o.height); break;
case "4/3": element_height = Utils.aspectRatioH(element_width, o.height); break;
case "auto": element_height = Utils.aspectRatioH(element_width, "16/9"); break;
default: element_height = o.height;
}
element.css({
height: element_height
});
var x = element_width / 2 - o.lensSize / 2;
var y = element_height / 2 - o.lensSize / 2;
if (o.magnifierMode === "glass") {
magnifier = $("<div>").addClass("image-magnifier-glass").appendTo(element);
magnifier.css({
width: o.lensSize,
height: o.lensSize,
borderRadius: o.lensType !== "circle" ? 0 : "50%",
top: y,
left: x,
backgroundImage: "url(" + image[0].src + ")",
backgroundRepeat: "no-repeat",
backgroundPosition: "-" + ((x * o.magnifierZoom) - o.lensSize / 4 + 4) + "px -" + ((y * o.magnifierZoom) - o.lensSize / 4 + 4) + "px",
backgroundSize: (image[0].width * o.magnifierZoom) + "px " + (image[0].height * o.magnifierZoom) + "px"
}).addClass(o.clsLens);
} else {
magnifier = $("<div>").addClass("image-magnifier-glass").appendTo(element);
magnifier.css({
width: o.lensSize,
height: o.lensSize,
borderRadius: 0,
borderWidth: 1,
top: y,
left: x
}).addClass(o.clsLens);
if (!Utils.isValue(o.magnifierZoomElement) || $(o.magnifierZoomElement).length === 0) {
this.zoomElement = $("<div>").insertAfter(element);
} else {
this.zoomElement = $(o.magnifierZoomElement);
}
var zoom_element_width = magnifier[0].offsetWidth * o.magnifierZoom;
var zoom_element_height = magnifier[0].offsetHeight * o.magnifierZoom;
var cx = zoom_element_width / o.lensSize;
var cy = zoom_element_height / o.lensSize;
this.zoomElement.css({
width: zoom_element_width,
height: zoom_element_height,
backgroundImage: "url(" + image[0].src + ")",
backgroundRepeat: "no-repeat",
backgroundPosition: "-" + (x * cx) + "px -" + (y * cy) + "px",
backgroundSize: (image[0].width * cx) + "px " + (image[0].height * cy) + "px"
}).addClass(o.clsZoom);
}
},
_createEvents: function(){
var that = this, element = this.element, o = this.options;
var glass = element.find(".image-magnifier-glass");
var glass_size = glass[0].offsetWidth / 2;
var image = element.find("img")[0];
var zoomElement = this.zoomElement;
var cx, cy;
$(window).on(Metro.events.resize, function(){
var x = element.width() / 2 - o.lensSize / 2;
var y = element.height() / 2 - o.lensSize / 2;
if (o.magnifierMode === "glass") {
glass.css({
backgroundPosition: "-" + ((x * o.magnifierZoom) - o.lensSize / 4 + 4) + "px -" + ((y * o.magnifierZoom) - o.lensSize / 4 + 4) + "px",
backgroundSize: (image.width * o.magnifierZoom) + "px " + (image.height * o.magnifierZoom) + "px"
});
}
}, {ns: this.id})
if (o.magnifierMode !== "glass") {
cx = zoomElement[0].offsetWidth / glass_size / 2;
cy = zoomElement[0].offsetHeight / glass_size / 2;
zoomElement.css({
backgroundSize: (image.width * cx) + "px " + (image.height * cy) + "px"
});
}
var lens_move = function(pos){
var x, y;
var magic = 4, zoom = parseInt(o.magnifierZoom);
if (o.magnifierMode === "glass") {
x = pos.x;
y = pos.y;
if (x > image.width - (glass_size / zoom)) {
x = image.width - (glass_size / zoom);
}
if (x < glass_size / zoom) {
x = glass_size / zoom;
}
if (y > image.height - (glass_size / zoom)) {
y = image.height - (glass_size / zoom);
}
if (y < glass_size / zoom) {
y = glass_size / zoom;
}
glass.css({
top: y - glass_size,
left: x - glass_size,
backgroundPosition: "-" + ((x * zoom) - glass_size + magic) + "px -" + ((y * zoom) - glass_size + magic) + "px"
});
} else {
x = pos.x - (glass_size);
y = pos.y - (glass_size);
if (x > image.width - glass_size * 2) {x = image.width - glass_size * 2;}
if (x < 0) {x = 0;}
if (y > image.height - glass_size * 2) {y = image.height - glass_size * 2;}
if (y < 0) {y = 0;}
glass.css({
top: y,
left: x
});
zoomElement.css({
backgroundPosition: "-" + (x * cx) + "px -" + (y * cy) + "px"
});
}
};
element.on(Metro.events.move, function(e){
var pos = Utils.getCursorPosition(image, e);
lens_move(pos);
that._fireEvent("magnifier-move", {
pos: pos,
glass: glass[0],
zoomElement: zoomElement ? zoomElement[0] : undefined
});
e.preventDefault();
});
element.on(Metro.events.leave, function(){
var x = element.width() / 2 - o.lensSize / 2;
var y = element.height() / 2 - o.lensSize / 2;
glass.animate({
draw: {
top: y,
left: x
}
});
lens_move({
x: x + o.lensSize / 2, y: y + o.lensSize / 2
});
});
},
/* eslint-disable-next-line */
changeAttribute: function(attributeName){
},
destroy: function(){
var element = this.element;
element.off(Metro.events.move);
element.off(Metro.events.leave);
return element;
}
});
}(Metro, m4q));