I recently had some help here creating a justified gallery with hover overlay content. It is based on this justified gallery - http://miromannino.github.io/Justified-Gallery/
I have managed to create everything apart from getting it to be responsive.
I have create a JSFiddle to see anyone can help me.
I've been at this for a week.... hoping I can find the end of my journey here :-)
https://jsfiddle.net/747tgcec/
HTML (snippet)
<section id="gallery" class="bh" style="height: 611px;">
<div id="mygallery" class="justified-gallery" style="height: 2398.01027268233px;">
<div class="single_image" style="width: 350px; height: 260px; top: 0px; left: 0px; opacity: 1;">
<img src="http://dangoodeofficial.co.uk/wp-content/uploads/Dan-Goode-Img-2-350x260.jpg" style="width: 350px; height: 260px; margin-left: -175.5px; margin-top: -130.5px;">
<div class="image_overlay text-center">
<div class="wrapper">
<div class="view-bigger">
<a class="single_image" href="http://dangoodeofficial.co.uk/wp-content/uploads/Dan-Goode-Gallery-12.jpg" rel="gallery">Grow Icon</a>
</div>
<div class="download">
Download ICON
</div>
<div class="content">
<a target="_blank" href="https://twitter.com/share?url=http://www.dangoodofficial.co.uk/&text=Check out #DanGoodeMusic"><span>Tweet Me</span>#DanGoodeMusic</a>
</div>
</div>
</div>
</div>
<div class="single_image" style="width: 400px; height: 260px; top: 0px; left: 350px; opacity: 1;">
<img src="http://dangoodeofficial.co.uk/wp-content/uploads/Dan-Goode-Img-2-400x260.jpg" style="width: 400px; height: 260px; margin-left: -200.5px; margin-top: -130.5px;">
<div class="image_overlay text-center">
<div class="wrapper">
<div class="view-bigger">
<a class="single_image" href="http://dangoodeofficial.co.uk/wp-content/uploads/Dan-Goode-Gallery1.jpg" rel="gallery">View Bigger</a>
</div>
<div class="download">
Download
</div>
<div class="content">
<a target="_blank" href="https://twitter.com/share?url=http://www.thesaxman.com/&text=Check out #TheSaxManUK"><span>Click to Tweet</span>“Check out #TheSaxManUK”</a>
</div>
</div>
</div>
</div>
<div class="single_image" style="width: 400px; height: 260px; top: 0; left: 750px; opacity: 1;">
<img src="http://dangoodeofficial.co.uk/wp-content/uploads/Dan-Goode-Img-3-400x260.jpg" style="width: 400px; height: 260px; margin-left: -200.5px; margin-top: -130.5px;">
<div class="image_overlay text-center">
<div class="wrapper">
<div class="view-bigger">
<a class="single_image" href="http://thesaxman.com/wp-content/themes/thesaxman/library/img/gallery/image19.jpg" rel="gallery">View Bigger</a>
</div>
<div class="download">
Download
</div>
<div class="content">
<a target="_blank" href="https://twitter.com/share?url=http://www.thesaxman.com/&text=Check out #TheSaxManUK"><span>Click to Tweet</span>“Check out #TheSaxManUK”</a>
</div>
</div>
</div>
</div>
</div>
</section>
CSS
section#gallery {
background-color:
}
section#gallery div .image_overlay {
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
background-color: rgba(1, 62, 187,0.8);
opacity:0; position:absolute;
top:10px;
left:10px;
right:10px;
bottom:10px;
z-index:100;
display:block;
border:2px solid #bc0001;
border: 2px solid #ffffff
}
section#gallery div:hover>.image_overlay {
opacity:1;
}
section#gallery div .image_overlay .wrapper {
display: table;
width: 100%;
height: 100%;
position:relative;
}
section#gallery div .image_overlay .wrapper .content {
display: table-cell;
text-align: center;
vertical-align: middle;
color:rgba(255,255,255,1.00);font-size:22px;}
section#gallery div .image_overlay .wrapper .content a { color:rgba(255,255,255,1.00)
}
section#gallery div .image_overlay .wrapper .view-bigger {
position:absolute;
top:10px;
right:10px;
color:rgba(255,255,255,1.00);
}
section#gallery div .image_overlay .wrapper .view-bigger a {
color:rgba(255,255,255,1.00) !important
}
section#gallery div .image_overlay .wrapper .view-bigger a:after {
content:"\f504";
display:inline-block;
-webkit-font-smoothing:antialiased;
font:normal 20px/1 'dashicons';
vertical-align:top;
margin-left:5px;
}
section#gallery div .image_overlay .wrapper .download {
position:absolute;
bottom:10px;
left:10px;
color:rgba(255,255,255,1.00);
}
section#gallery div .image_overlay .wrapper .download a {
color:rgba(255,255,255,1.00) !important
}
section#gallery div .image_overlay .wrapper .download a:after {
content: "\f316";
display: inline-block;
-webkit-font-smoothing:
antialiased;font: normal 20px/1 'dashicons';
vertical-align: top;
margin-left:5px;
}
section#gallery div .image_overlay .wrapper .content span {
display:block;
font-size:30px;
font-family: "museo";}
.image_overlay {
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
background-color: rgba(1, 62, 187,0.8);
opacity: 0;
position: absolute;
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
z-index: 100;
display: block;
border: 1px solid rgba(255,255,255,1.00);
}
.image_overlay .wrapper {
display: table;
width: 100%;
height: 100%;
position: relative;
}
.image_overlay .wrapper .view-bigger {
position: absolute;
top: 10px;
right: 10px;
color: rgba(255,255,255,1.00);
}
.image_overlay .wrapper .download {
position: absolute;
bottom: 10px;
left: 10px;
color: rgba(255,255,255,1.00);
}
.image_overlay .wrapper .content {
font-family: Righteous;
display: table-cell;
text-align: center;
vertical-align: middle;
color: rgba(255,255,255,1.00);
font-size: 32px;
}
.image_overlay .wrapper .content a {
color: rgba(255,255,255,1.00);
}
.image_overlay .wrapper .content span {
display: block;
font-size: 40px;
font-family: "museo";
}
#-webkit-keyframes justified-gallery-show-caption-animation {
from {
opacity: 0
}
to {
opacity: .7
}
}
#-moz-keyframes justified-gallery-show-caption-animation {
from {
opacity: 0
}
to {
opacity: .7
}
}
#-o-keyframes justified-gallery-show-caption-animation {
from {
opacity: 0
}
to {
opacity: .7
}
}
#keyframes justified-gallery-show-caption-animation {
from {
opacity: 0
}
to {
opacity: .7
}
}
#-webkit-keyframes justified-gallery-show-entry-animation {
from {
opacity: 0
}
to {
opacity: 1
}
}
#-moz-keyframes justified-gallery-show-entry-animation {
from {
opacity: 0
}
to {
opacity: 1
}
}
#-o-keyframes justified-gallery-show-entry-animation {
from {
opacity: 0
}
to {
opacity: 1
}
}
#keyframes justified-gallery-show-entry-animation {
from {
opacity: 0
}
to {
opacity: 1
}
}
.justified-gallery {
width: 100%;
position: relative;
overflow: hidden
}
.justified-gallery>a, .justified-gallery>div {
position: absolute;
display: inline-block;
overflow: hidden;
opacity: 0;
filter: alpha(opacity=0)
}
.justified-gallery>a>img, .justified-gallery>div>img {
position: absolute;
top: 50%;
left: 50%;
margin: 0;
padding: 0;
border: 0
}
.justified-gallery>a>img, .justified-gallery>div>img:hover {
position: absolute;
top: 50%;
left: 50%;
margin: 0;
padding: 0;
border: 0;
}
JAVASCRIPT
! function(a) {
a.fn.justifiedGallery = function(b) {
function c(a, b, c) {
var d;
return d = a > b ? a : b, 100 >= d ? c.settings.sizeRangeSuffixes
.lt100 : 240 >= d ? c.settings.sizeRangeSuffixes.lt240 :
320 >= d ? c.settings.sizeRangeSuffixes.lt320 : 500 >=
d ? c.settings.sizeRangeSuffixes.lt500 : 640 >= d ? c.settings
.sizeRangeSuffixes.lt640 : c.settings.sizeRangeSuffixes
.lt1024
}
function d(a, b) {
return -1 !== a.indexOf(b, a.length - b.length)
}
function e(a, b) {
return a.substring(0, a.length - b.length)
}
function f(a, b) {
var c = !1;
for (var e in b.settings.sizeRangeSuffixes)
if (0 !== b.settings.sizeRangeSuffixes[e].length) {
if (d(a, b.settings.sizeRangeSuffixes[e])) return b
.settings.sizeRangeSuffixes[e]
} else c = !0;
if (c) return "";
throw "unknown suffix for " + a
}
function g(a, b, d, g) {
var h = a.match(g.settings.extension),
i = null != h ? h[0] : "",
j = a.replace(g.settings.extension, "");
return j = e(j, f(j, g)), j += c(b, d, g) + i
}
function h(b) {
var c = a(b.currentTarget).find(".caption");
b.data.settings.cssAnimation ? c.addClass("caption-visible")
.removeClass("caption-hidden") : c.stop().fadeTo(b.data
.settings.captionSettings.animationDuration, b.data
.settings.captionSettings.visibleOpacity)
}
function i(b) {
var c = a(b.currentTarget).find(".caption");
b.data.settings.cssAnimation ? c.removeClass(
"caption-visible").removeClass("caption-hidden") :
c.stop().fadeTo(b.data.settings.captionSettings.animationDuration,
b.data.settings.captionSettings.nonVisibleOpacity)
}
function j(a, b, c) {
c.settings.cssAnimation ? (a.addClass("entry-visible"), b()) :
a.stop().fadeTo(c.settings.imagesAnimationDuration, 1,
b)
}
function k(a, b) {
b.settings.cssAnimation ? a.removeClass("entry-visible") :
a.stop().fadeTo(0, 0)
}
function l(b, c, d, e, f, k, l) {
function m() {
o !== p && n.attr("src", p)
}
var n = b.find("img");
n.css("width", e), n.css("height", f), n.css("margin-left", -
e / 2), n.css("margin-top", -f / 2), b.width(e), b.height(
k), b.css("top", d), b.css("left", c);
var o = n.attr("src"),
p = g(o, e, f, l);
n.one("error", function() {
n.attr("src", n.data("jg.originalSrc"))
}), "skipped" === n.data("jg.loaded") ? n.one("load",
function() {
j(b, m, l), n.data("jg.loaded", "loaded")
}) : j(b, m, l);
var q = b.data("jg.captionMouseEvents");
if (l.settings.captions === !0) {
var r = b.find(".caption");
if (0 === r.length) {
var s = n.attr("alt");
"undefined" == typeof s && (s = b.attr("title")),
"undefined" != typeof s && (r = a(
'<div class="caption">' + s + "</div>"),
b.append(r))
}
0 !== r.length && (l.settings.cssAnimation || r.stop().fadeTo(
l.settings.imagesAnimationDuration, l.settings
.captionSettings.nonVisibleOpacity),
"undefined" == typeof q && (q = {
mouseenter: h,
mouseleave: i
}, b.on("mouseenter", void 0, l, q.mouseenter),
b.on("mouseleave", void 0, l, q.mouseleave),
b.data("jg.captionMouseEvents", q)))
} else "undefined" != typeof q && (b.off("mouseenter", void 0,
l, q.mouseenter), b.off("mouseleave", void 0, l,
q.mouseleave), b.removeData(
"jg.captionMouseEvents"))
}
function m(a, b) {
var c, d, e, f, g, h, i = a.settings,
j = !0,
k = 0,
l = a.galleryWidth - (a.buildingRow.entriesBuff.length -
1) * i.margins,
m = l / a.buildingRow.aspectRatio,
n = a.buildingRow.width / l > i.justifyThreshold;
if (b && "hide" === i.lastRow && !n) {
for (c = 0; c < a.buildingRow.entriesBuff.length; c++) d =
a.buildingRow.entriesBuff[c], i.cssAnimation ? d.removeClass(
"entry-visible") : d.stop().fadeTo(0, 0);
return -1
}
for (b && !n && "nojustify" === i.lastRow && (j = !1), c =
0; c < a.buildingRow.entriesBuff.length; c++) e = a.buildingRow
.entriesBuff[c].find("img"), f = e.data("jg.imgw") / e.data(
"jg.imgh"), j ? (g = m * f, h = m) : (g = i.rowHeight *
f, h = i.rowHeight), e.data("jg.jimgw", Math.ceil(g)),
e.data("jg.jimgh", Math.ceil(h)), (0 === c || k > h) &&
(k = h);
return i.fixedHeight && k > i.rowHeight && (k = i.rowHeight), {
minHeight: k,
justify: j
}
}
function n(a) {
a.lastAnalyzedIndex = -1, a.buildingRow.entriesBuff = [], a
.buildingRow.aspectRatio = 0, a.buildingRow.width = 0,
a.offY = 0
}
function o(a, b) {
var c, d, e, f, g = a.settings,
h = 0;
if (f = m(a, b), e = f.minHeight, b && "hide" === g.lastRow &&
-1 === e) return a.buildingRow.entriesBuff = [], a.buildingRow
.aspectRatio = 0, void(a.buildingRow.width = 0);
g.maxRowHeight > 0 && g.maxRowHeight < e ? e = g.maxRowHeight :
0 === g.maxRowHeight && 1.5 * g.rowHeight < e && (e = 1.5 * g.rowHeight);
for (var i = 0; i < a.buildingRow.entriesBuff.length; i++) c =
a.buildingRow.entriesBuff[i], d = c.find("img"), l(c, h,
a.offY, d.data("jg.jimgw"), d.data("jg.jimgh"), e,
a), h += d.data("jg.jimgw") + g.margins;
a.$gallery.height(a.offY + e + (a.spinner.active ? a.spinner
.$el.innerHeight() : 0)), (!b || e <= a.settings.rowHeight &&
f.justify) && (a.offY += e + a.settings.margins, a.buildingRow
.entriesBuff = [], a.buildingRow.aspectRatio = 0, a
.buildingRow.width = 0, a.$gallery.trigger(
"jg.rowflush"))
}
function p(a) {
a.checkWidthIntervalId = setInterval(function() {
var b = parseInt(a.$gallery.width(), 10);
a.galleryWidth !== b && (a.galleryWidth = b, n(
a), t(a, !0))
}, a.settings.refreshTime)
}
function q(a) {
clearInterval(a.intervalId), a.intervalId = setInterval(
function() {
a.phase < a.$points.length ? a.$points.eq(a.phase)
.fadeTo(a.timeslot, 1) : a.$points.eq(a.phase -
a.$points.length).fadeTo(a.timeslot, 0),
a.phase = (a.phase + 1) % (2 * a.$points.length)
}, a.timeslot)
}
function r(a) {
clearInterval(a.intervalId), a.intervalId = null
}
function s(a) {
a.yield.flushed = 0, null !== a.imgAnalyzerTimeout &&
clearTimeout(a.imgAnalyzerTimeout)
}
function t(a, b) {
s(a), a.imgAnalyzerTimeout = setTimeout(function() {
u(a, b)
}, .001), u(a, b)
}
function u(b, c) {
for (var d, e = b.settings, f = b.lastAnalyzedIndex + 1; f <
b.entries.length; f++) {
var g = a(b.entries[f]),
h = g.find("img");
if (h.data("jg.loaded") === !0 || "skipped" === h.data(
"jg.loaded")) {
d = f >= b.entries.length - 1;
var i = b.galleryWidth - (b.buildingRow.entriesBuff
.length - 1) * e.margins,
j = h.data("jg.imgw") / h.data("jg.imgh");
if (i / (b.buildingRow.aspectRatio + j) < e.rowHeight &&
(o(b, d), ++b.yield.flushed >= b.yield.every))
return void t(b, c);
b.buildingRow.entriesBuff.push(g), b.buildingRow.aspectRatio +=
j, b.buildingRow.width += j * e.rowHeight, b.lastAnalyzedIndex =
f
} else if ("error" !== h.data("jg.loaded")) return
}
b.buildingRow.entriesBuff.length > 0 && o(b, !0), b.spinner
.active && (b.spinner.active = !1, b.$gallery.height(b.$gallery
.height() - b.spinner.$el.innerHeight()), b.spinner
.$el.detach(), r(b.spinner)), s(b), b.$gallery.trigger(
c ? "jg.resize" : "jg.complete")
}
function v(a) {
function b(a) {
if ("string" != typeof d.sizeRangeSuffixes[a]) throw "sizeRangeSuffixes." +
a + " must be a string"
}
function c(a, b) {
if ("string" == typeof a[b]) {
if (a[b] = parseFloat(a[b], 10), isNaN(a[b]))
throw "invalid number for " + b
} else {
if ("number" != typeof a[b]) throw b +
" must be a number";
if (isNaN(a[b])) throw "invalid number for " +
b
}
}
var d = a.settings;
if ("object" != typeof d.sizeRangeSuffixes) throw "sizeRangeSuffixes must be defined and must be an object";
if (b("lt100"), b("lt240"), b("lt320"), b("lt500"), b(
"lt640"), b("lt1024"), c(d, "rowHeight"), c(d,
"maxRowHeight"), d.maxRowHeight > 0 && d.maxRowHeight <
d.rowHeight && (d.maxRowHeight = d.rowHeight), c(d,
"margins"), "nojustify" !== d.lastRow && "justify" !==
d.lastRow && "hide" !== d.lastRow) throw 'lastRow must be "nojustify", "justify" or "hide"';
if (c(d, "justifyThreshold"), d.justifyThreshold < 0 || d.justifyThreshold >
1) throw "justifyThreshold must be in the interval [0,1]";
if ("boolean" != typeof d.cssAnimation) throw "cssAnimation must be a boolean";
if (c(d.captionSettings, "animationDuration"), c(d,
"imagesAnimationDuration"), c(d.captionSettings,
"visibleOpacity"), d.captionSettings.visibleOpacity <
0 || d.captionSettings.visibleOpacity > 1) throw "captionSettings.visibleOpacity must be in the interval [0, 1]";
if (c(d.captionSettings, "nonVisibleOpacity"), d.captionSettings
.visibleOpacity < 0 || d.captionSettings.visibleOpacity >
1) throw "captionSettings.nonVisibleOpacity must be in the interval [0, 1]";
if ("boolean" != typeof d.fixedHeight) throw "fixedHeight must be a boolean";
if ("boolean" != typeof d.captions) throw "captions must be a boolean";
if (c(d, "refreshTime"), "boolean" != typeof d.randomize)
throw "randomize must be a boolean"
}
var w = {
sizeRangeSuffixes: {
lt100: "_t",
lt240: "_m",
lt320: "_n",
lt500: "",
lt640: "_z",
lt1024: "_b"
},
rowHeight: 120,
maxRowHeight: 0,
margins: 1,
lastRow: "nojustify",
justifyThreshold: .75,
fixedHeight: !1,
waitThumbnailsLoad: !0,
captions: !0,
cssAnimation: !1,
imagesAnimationDuration: 500,
captionSettings: {
animationDuration: 500,
visibleOpacity: .7,
nonVisibleOpacity: 0
},
rel: null,
target: null,
extension: /\.[^.\\/]+$/,
refreshTime: 100,
randomize: !1
};
return this.each(function(c, d) {
var e = a(d);
e.addClass("justified-gallery");
var f = e.data("jg.context");
if ("undefined" == typeof f) {
if ("undefined" != typeof b && null !== b &&
"object" != typeof b) throw "The argument must be an object";
var g = a(
'<div class="spinner"><span></span><span></span><span></span></div>'
);
f = {
settings: a.extend({}, w, b),
imgAnalyzerTimeout: null,
entries: null,
buildingRow: {
entriesBuff: [],
width: 0,
aspectRatio: 0
},
lastAnalyzedIndex: -1,
"yield": {
every: 2,
flushed: 0
},
offY: 0,
spinner: {
active: !1,
phase: 0,
timeslot: 150,
$el: g,
$points: g.find("span"),
intervalId: null
},
checkWidthIntervalId: null,
galleryWidth: e.width(),
$gallery: e
}, e.data("jg.context", f)
} else if ("norewind" === b)
for (var h = 0; h < f.buildingRow.entriesBuff.length; h++)
k(f.buildingRow.entriesBuff[h], f);
else f.settings = a.extend({}, f.settings, b), n(f); if (
v(f), f.entries = e.find("> a, > div:not(.spinner)")
.toArray(), 0 !== f.entries.length) {
f.settings.randomize && (f.entries.sort(function() {
return 2 * Math.random() - 1
}), a.each(f.entries, function() {
a(this).appendTo(e)
}));
var i = !1;
a.each(f.entries, function(b, c) {
var d = a(c),
g = d.find("img");
if (g.data("jg.loaded") !== !0 &&
"skipped" !== g.data("jg.loaded")) {
null !== f.settings.rel && d.attr(
"rel", f.settings.rel),
null !== f.settings.target && d
.attr("target", f.settings.target);
var h = "undefined" != typeof g.data(
"safe-src") ? g.data(
"safe-src") : g.attr("src");
g.data("jg.originalSrc", h), g.attr(
"src", h);
var j = parseInt(g.attr("width"),
10),
k = parseInt(g.attr("height"),
10);
if (f.settings.waitThumbnailsLoad !==
!0 && !isNaN(j) && !isNaN(k))
return g.data("jg.imgw", j), g.data(
"jg.imgh", k), g.data(
"jg.loaded", "skipped"),
t(f, !1), !0;
g.data("jg.loaded", !1), i = !0, f.spinner
.active === !1 && (f.spinner.active = !
0, e.append(f.spinner.$el),
e.height(f.offY + f.spinner
.$el.innerHeight()), q(
f.spinner));
var l = new Image,
m = a(l);
m.one("load", function() {
g.off("load error"), g.data(
"jg.imgw", l.width
), g.data("jg.imgh",
l.height), g.data(
"jg.loaded", !0
), t(f, !1)
}), m.one("error", function() {
g.off("load error"), g.data(
"jg.loaded",
"error"), t(f, !
1)
}), l.src = h
}
}), i || t(f, !1), p(f)
}
})
}
}(jQuery);
Related
ive got a Vue component which lets me zoom in on an image, using the mouse wheel works fine, however pinch zoom behaves strangely.
Basically if you put 2 fingers on the screen far apart it zooms in a lot, put them in closer together and it zooms in a bit. What should happen is it doesn't zoom in or out until you actually move your fingers in or out.
Any ideas?
Vue.component('test', {
data() {
return {
loading: false,
loop: true,
speed: 8,
speedController: 0,
zoomEnabled: true,
zoomLevels: [1, 1.5, 2, 2.5, 3],
zoomLevel: 1,
frame: 1,
images: [],
imagesPreloaded: 0,
spinEnabled: true,
spinAuto: false,
reverse: false,
viewportScale: 0.3,
viewportEnabled: true,
viewportOpacity: 0.8,
lastX: 0,
lastY: 0,
startX: 0,
startY: 0,
translateX: 0,
translateY: 0,
isMoving: false,
isDragging: false,
lastPinch: 0,
animationRequestID: 0,
spinStart: null,
spinThen: Date.now(),
fps: 1000 / 8,
axiosRequest: null,
$clickEvent: null,
$moveEvent: null,
output: ''
};
},
mounted() {
window.addEventListener('mouseup', this.handleEnd);
window.addEventListener('touchend', this.handleEnd);
window.addEventListener('resize', this.fetch);
},
beforeDestroy() {
window.removeEventListener('mouseup', this.handleEnd);
window.removeEventListener('touchend', this.handleEnd);
},
methods: {
handleSlider(event) {
this.frame = Number(event.target.value);
},
zoom(direction) {
if (this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + direction] === undefined) {
return;
}
let current = this.zoomLevels.indexOf(this.closestZoom);
let index = current += direction;
if (direction === 0) {
index = 0;
}
this.zoomLevel = this.zoomLevels[index];
this.translate(null, true);
},
zoomWheel($event) {
this.zoomLevel += $event.deltaY * -0.01;
if (this.zoomLevel < 1) {
this.zoomLevel = 1;
}
$event.preventDefault();
let maxZoom = this.zoomLevels[this.zoomLevels.length - 1];
this.zoomLevel = Math.min(Math.max(.125, this.zoomLevel), maxZoom);
this.translate(null, true);
},
zoomPinch($event) {
let curDiff = Math.abs($event.touches[0].clientX - $event.touches[1].clientX);
$event.deltaY = this.lastPinch - curDiff;
this.zoomWheel($event);
this.lastPinch = curDiff;
},
handleStart($event) {
if ($event.button && $event.button !== 0) {
return;
}
this.$clickEvent = $event;
if (this.animationRequestID !== 0) {
this.spinStop();
}
this.isMoving = true;
this.isDragging = true;
// this.startTouchX = [ $event.touches[0].clientX, $event.touches[1].clientX ];
// this.startTouchY = [ [ $event.touches[0].clientY, $event.touches[1].clientY ] ];
this.startX = this.$clickEvent.pageX || this.$clickEvent.touches[0].pageX;
this.startY = this.$clickEvent.pageY || this.$clickEvent.touches[0].pageY;
},
handleMove($event, viewport) {
if ($event.button && $event.button !== 0) {
return;
}
if ($event.touches && $event.touches.length > 1) {
this.zoomPinch($event);
return;
}
this.$moveEvent = $event;
if (this.isMoving && this.isDragging) {
const positions = {
x: $event.pageX || $event.touches[0].pageX,
y: $event.pageY || $event.touches[0].pageY
}
if (this.zoomLevel !== 1) {
this.translate(positions, null, viewport);
}
if (this.zoomLevel === 1) {
this.changeFrame(positions);
}
this.lastX = positions.x;
this.lastY = positions.y;
}
},
handleEnd($event) {
if ($event.button && $event.button !== 0) {
return;
}
this.isMoving = false;
},
spin(index) {
let i = index;
if (i >= this.images.length) {
i = 1;
}
this.animationRequestID = window.requestAnimationFrame(() => this.spin(i));
let now = Date.now();
let elapsed = now - this.spinThen;
if (elapsed > this.fps) {
this.spinThen = now - (elapsed % this.fps);
this.frame = i;
i += 1;
}
},
spinToggle() {
if (this.animationRequestID === 0 && this.zoomLevel === 1) {
this.spin(this.frame);
return;
}
this.spinStop();
},
spinStop() {
if (this.animationRequestID) {
window.cancelAnimationFrame(this.animationRequestID);
this.animationRequestID = 0;
}
},
translate(positions, zooming, viewport) {
if (this.$moveEvent) {
this.$moveEvent.preventDefault();
}
window.requestAnimationFrame(() => {
positions = positions || {
x: this.startX,
y: this.startY
};
if (viewport) {
this._translateFromViewport(positions);
} else {
this._translateFromImage(positions, zooming);
}
this.startX = positions.x;
this.startY = positions.y;
});
},
/**
* #param positions
* #private
*/
_translateFromViewport: function(positions) {
let move = {
x: Math.floor(positions.x - this.startX),
y: Math.floor(positions.y - this.startY)
};
let box = this.$refs.viewportBox.getBoundingClientRect();
let container = this.$refs.viewportContainer.getBoundingClientRect();
// Amount of pixels moved within animation frame, adjust based on viewport scale.
// Zoom level doesn't matter as image scale doesn't move, so box is moving same amount of pixels.
let moveAmountX = (move.x / this.viewportScale);
let moveAmountY = (move.y / this.viewportScale);
// Find the current offset of the container bounds, calculate new offset based on movement amount
let calculatedOffset = {
left: (container.left - box.left) - moveAmountX,
right: (container.right - box.right) - moveAmountX,
top: (container.top - box.top) - moveAmountY,
bottom: (container.bottom - box.bottom) - moveAmountY
};
this.output = JSON.stringify(calculatedOffset);
// Only move if the calculated new offset is not out of container bounds
// Reverse the movement as moving box in same direction as cursor rather than the image.
if (calculatedOffset.left <= 0 && calculatedOffset.right >= 0) {
this.translateX += -moveAmountX;
}
if (calculatedOffset.top <= 0 && calculatedOffset.bottom >= 0) {
this.translateY += -moveAmountY;
}
},
_translateFromImage: function(positions, zooming) {
let move = {
x: Math.floor(positions.x - this.startX),
y: Math.floor(positions.y - this.startY)
};
let image = this.$refs.image.getBoundingClientRect();
let container = this.$refs.container.getBoundingClientRect();
let moveAmountX = move.x * this.zoomLevel;
let moveAmountY = move.y * this.zoomLevel;
let calculatedOffset = {
left: (container.left - image.left) - moveAmountX,
right: (container.right - image.right) - moveAmountX,
top: (container.top - image.top) - moveAmountY,
bottom: (container.bottom - image.bottom) - moveAmountY
};
if (zooming) {
if (calculatedOffset.left <= 0) {
this.translateX += calculatedOffset.left;
}
if (calculatedOffset.right >= 0) {
this.translateX += calculatedOffset.right;
}
if (calculatedOffset.top <= 0) {
this.translateY += calculatedOffset.top;
}
if (calculatedOffset.bottom >= 0) {
this.translateY += calculatedOffset.bottom;
}
}
if (calculatedOffset.left >= 0 && calculatedOffset.right <= 0) {
this.translateX += move.x / this.zoomLevel;
}
if (calculatedOffset.top >= 0 && calculatedOffset.bottom <= 0) {
this.translateY += move.y / this.zoomLevel;
}
},
changeFrame(positions) {
this.speedController += 1;
if (this.speedController < this.speed) {
return;
}
if (this.speedController > this.speed) {
this.speedController = 0;
}
if (positions.x > this.lastX) {
if (this.frame >= 0 && this.frame < this.images.length) {
this.frame += 1;
} else if (this.loop) {
this.frame = 1;
}
} else if (positions.x < this.lastX) {
if (this.frame >= 0 && this.frame - 1 > 0) {
this.frame -= 1;
} else if (this.loop) {
this.frame = this.images.length;
}
}
}
},
watch: {
zoomLevel: function() {
if (this.zoomLevel !== 1 && this.animationRequestID !== 0) {
this.spinStop();
}
}
},
computed: {
closestZoom: function() {
return this.zoomLevels.reduce((a, b) => {
return Math.abs(b - this.zoomLevel) < Math.abs(a - this.zoomLevel) ? b : a;
});
},
imageSet: function() {
return this.images.map(image => {
return image[this.closestZoom].url;
});
},
preloadProgress: function() {
return Math.floor(this.imagesPreloaded / this.images.length * 100);
},
currentPath: function() {
return this.images[this.frame - 1][this.closestZoom].url;
},
nextZoomLevel: function() {
if (this.zoomLevels.indexOf(this.closestZoom) === this.zoomLevels.length - 1) {
return this.zoomLevels[0];
}
return this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + 1];
},
viewportTransform: function() {
if (this.viewportEnabled) {
let translateX = -((this.translateX * this.viewportScale) * this.zoomLevel);
let translateY = -((this.translateY * this.viewportScale) * this.zoomLevel);
return `scale(${1 / this.zoomLevel}) translateX(${translateX}px) translateY(${translateY}px)`;
}
},
transform: function() {
return `scale(${this.zoomLevel}) translateX(${this.translateX}px) translateY(${this.translateY}px)`;
},
canZoomIn: function() {
return this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + 1] === undefined
},
canZoomOut: function() {
return this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + -1] === undefined
}
},
template: '#template'
});
window.vue = new Vue({}).$mount('#app');
.media-360-viewer {
position: relative;
overflow: hidden;
display: inline-block;
background: #000;
width: 100%;
transition: filter .2s ease-in-out;
&__image {
width: 100%;
cursor: grab;
&.isTranslating {
cursor: grabbing;
}
&.loading {
filter: blur(4px);
}
}
&__loader {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .5);
* {
user-select: none;
}
&>svg {
width: 100%;
height: 100%;
transform: rotate(270deg);
}
&--text {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
p {
font-size: 100%;
font-weight: bold;
color: #fff;
&.large {
font-size: 150%;
}
}
}
&--background {
stroke-dasharray: 0;
stroke-dashoffset: 0;
stroke: rgba(0, 0, 0, .7);
stroke-width: 25px;
}
&--cover {
stroke-dasharray: 200%;
stroke: #848484;
stroke-width: 15px;
stroke-linecap: round;
}
&--background,
&--cover {
fill: transparent;
}
}
&__viewport {
position: absolute;
top: 10px;
left: 10px;
z-index: 2;
overflow: hidden;
&--image {
width: 100%;
pointer-events: none;
}
&--zoom {
position: absolute;
bottom: 5px;
right: 5px;
color: #fff;
z-index: 3;
font-size: 12px;
pointer-events: none;
}
&--square {
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
box-shadow: rgba(0, 0, 0, .6) 0 0 0 10000px;
cursor: grab;
transition: background ease-in-out .1s;
&:hover {
background: rgba(255, 255, 255, .2);
}
}
}
&__tools {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 10px;
&>a {
margin: 0 5px;
color: #000;
background: #fff;
border-radius: 50%;
width: 40px;
text-align: center;
line-height: 40px;
&[disabled] {
opacity: .5;
cursor: not-allowed;
&:hover {
color: #000;
background: #fff;
}
}
&:hover {
background: #000;
color: #fff;
}
}
&--autoplay {
&:before {
font-family: 'ClickIcons';
content: '\ea81';
}
&.active:before {
content: '\eb48';
}
}
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<test class="test"></test>
</div>
<script type="text/x-template" id="template">
<div>
<div class="media-360-viewer" ref="container">
<img tabindex="1" ref="image" draggable="false" src="https://s3-eu-west-1.amazonaws.com/crash.net/visordown.com/styles/amp_1200/s3/2020_YAM_YZF1000R1SPL_EU_BWM2_STA_001-70560.jpg?itok=5bisLKmj" :style="{ transform: transform }" class="media-360-viewer__image"
#touchend="handleEnd" #touchmove="handleMove" #touchstart="handleStart" #wheel="zoomWheel" alt="360 Image" />
</div>
</div>
</script>
I'm not sure I understand your problem correctly but as I try I think the problem of your code is on this line:
$event.deltaY = this.lastPinch - curDiff;
It seems this.lastPinch is hold the delta of previous touchmove event so for the first time of event you should ignore it and clear when touchend.
...
zoomPinch ($event) {
...
if (this.lastPinch) {
$event.deltaY = this.lastPinch - curDiff;
this.zoomWheel($event);
}
...
}
...
handleEnd ($event) {
...
this.lastPinch = 0
}
...
Vue.component('test', {
data() {
return {
loading: false,
loop: true,
speed: 8,
speedController: 0,
zoomEnabled: true,
zoomLevels: [1, 1.5, 2, 2.5, 3],
zoomLevel: 1,
frame: 1,
images: [],
imagesPreloaded: 0,
spinEnabled: true,
spinAuto: false,
reverse: false,
viewportScale: 0.3,
viewportEnabled: true,
viewportOpacity: 0.8,
lastX: 0,
lastY: 0,
startX: 0,
startY: 0,
translateX: 0,
translateY: 0,
isMoving: false,
isDragging: false,
lastPinch: 0,
animationRequestID: 0,
spinStart: null,
spinThen: Date.now(),
fps: 1000 / 8,
axiosRequest: null,
$clickEvent: null,
$moveEvent: null,
output: ''
};
},
mounted() {
window.addEventListener('mouseup', this.handleEnd);
window.addEventListener('touchend', this.handleEnd);
window.addEventListener('resize', this.fetch);
},
beforeDestroy() {
window.removeEventListener('mouseup', this.handleEnd);
window.removeEventListener('touchend', this.handleEnd);
},
methods: {
handleSlider(event) {
this.frame = Number(event.target.value);
},
zoom(direction) {
if (this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + direction] === undefined) {
return;
}
let current = this.zoomLevels.indexOf(this.closestZoom);
let index = current += direction;
if (direction === 0) {
index = 0;
}
this.zoomLevel = this.zoomLevels[index];
this.translate(null, true);
},
zoomWheel($event) {
this.zoomLevel += $event.deltaY * -0.01;
if (this.zoomLevel < 1) {
this.zoomLevel = 1;
}
$event.preventDefault();
let maxZoom = this.zoomLevels[this.zoomLevels.length - 1];
this.zoomLevel = Math.min(Math.max(.125, this.zoomLevel), maxZoom);
this.translate(null, true);
},
zoomPinch($event) {
let curDiff = Math.abs($event.touches[0].clientX - $event.touches[1].clientX);
if (this.lastPinch) {
$event.deltaY = this.lastPinch - curDiff;
this.zoomWheel($event);
}
this.lastPinch = curDiff;
},
handleStart($event) {
if ($event.button && $event.button !== 0) {
return;
}
this.$clickEvent = $event;
if (this.animationRequestID !== 0) {
this.spinStop();
}
this.isMoving = true;
this.isDragging = true;
// this.startTouchX = [ $event.touches[0].clientX, $event.touches[1].clientX ];
// this.startTouchY = [ [ $event.touches[0].clientY, $event.touches[1].clientY ] ];
this.startX = this.$clickEvent.pageX || this.$clickEvent.touches[0].pageX;
this.startY = this.$clickEvent.pageY || this.$clickEvent.touches[0].pageY;
},
handleMove($event, viewport) {
if ($event.button && $event.button !== 0) {
return;
}
if ($event.touches && $event.touches.length > 1) {
this.zoomPinch($event);
return;
}
this.$moveEvent = $event;
if (this.isMoving && this.isDragging) {
const positions = {
x: $event.pageX || $event.touches[0].pageX,
y: $event.pageY || $event.touches[0].pageY
}
if (this.zoomLevel !== 1) {
this.translate(positions, null, viewport);
}
if (this.zoomLevel === 1) {
this.changeFrame(positions);
}
this.lastX = positions.x;
this.lastY = positions.y;
}
},
handleEnd($event) {
if ($event.button && $event.button !== 0) {
return;
}
this.isMoving = false;
this.lastPinch = 0;
},
spin(index) {
let i = index;
if (i >= this.images.length) {
i = 1;
}
this.animationRequestID = window.requestAnimationFrame(() => this.spin(i));
let now = Date.now();
let elapsed = now - this.spinThen;
if (elapsed > this.fps) {
this.spinThen = now - (elapsed % this.fps);
this.frame = i;
i += 1;
}
},
spinToggle() {
if (this.animationRequestID === 0 && this.zoomLevel === 1) {
this.spin(this.frame);
return;
}
this.spinStop();
},
spinStop() {
if (this.animationRequestID) {
window.cancelAnimationFrame(this.animationRequestID);
this.animationRequestID = 0;
}
},
translate(positions, zooming, viewport) {
if (this.$moveEvent) {
this.$moveEvent.preventDefault();
}
window.requestAnimationFrame(() => {
positions = positions || {
x: this.startX,
y: this.startY
};
if (viewport) {
this._translateFromViewport(positions);
} else {
this._translateFromImage(positions, zooming);
}
this.startX = positions.x;
this.startY = positions.y;
});
},
/**
* #param positions
* #private
*/
_translateFromViewport: function(positions) {
let move = {
x: Math.floor(positions.x - this.startX),
y: Math.floor(positions.y - this.startY)
};
let box = this.$refs.viewportBox.getBoundingClientRect();
let container = this.$refs.viewportContainer.getBoundingClientRect();
// Amount of pixels moved within animation frame, adjust based on viewport scale.
// Zoom level doesn't matter as image scale doesn't move, so box is moving same amount of pixels.
let moveAmountX = (move.x / this.viewportScale);
let moveAmountY = (move.y / this.viewportScale);
// Find the current offset of the container bounds, calculate new offset based on movement amount
let calculatedOffset = {
left: (container.left - box.left) - moveAmountX,
right: (container.right - box.right) - moveAmountX,
top: (container.top - box.top) - moveAmountY,
bottom: (container.bottom - box.bottom) - moveAmountY
};
this.output = JSON.stringify(calculatedOffset);
// Only move if the calculated new offset is not out of container bounds
// Reverse the movement as moving box in same direction as cursor rather than the image.
if (calculatedOffset.left <= 0 && calculatedOffset.right >= 0) {
this.translateX += -moveAmountX;
}
if (calculatedOffset.top <= 0 && calculatedOffset.bottom >= 0) {
this.translateY += -moveAmountY;
}
},
_translateFromImage: function(positions, zooming) {
let move = {
x: Math.floor(positions.x - this.startX),
y: Math.floor(positions.y - this.startY)
};
let image = this.$refs.image.getBoundingClientRect();
let container = this.$refs.container.getBoundingClientRect();
let moveAmountX = move.x * this.zoomLevel;
let moveAmountY = move.y * this.zoomLevel;
let calculatedOffset = {
left: (container.left - image.left) - moveAmountX,
right: (container.right - image.right) - moveAmountX,
top: (container.top - image.top) - moveAmountY,
bottom: (container.bottom - image.bottom) - moveAmountY
};
if (zooming) {
if (calculatedOffset.left <= 0) {
this.translateX += calculatedOffset.left;
}
if (calculatedOffset.right >= 0) {
this.translateX += calculatedOffset.right;
}
if (calculatedOffset.top <= 0) {
this.translateY += calculatedOffset.top;
}
if (calculatedOffset.bottom >= 0) {
this.translateY += calculatedOffset.bottom;
}
}
if (calculatedOffset.left >= 0 && calculatedOffset.right <= 0) {
this.translateX += move.x / this.zoomLevel;
}
if (calculatedOffset.top >= 0 && calculatedOffset.bottom <= 0) {
this.translateY += move.y / this.zoomLevel;
}
},
changeFrame(positions) {
this.speedController += 1;
if (this.speedController < this.speed) {
return;
}
if (this.speedController > this.speed) {
this.speedController = 0;
}
if (positions.x > this.lastX) {
if (this.frame >= 0 && this.frame < this.images.length) {
this.frame += 1;
} else if (this.loop) {
this.frame = 1;
}
} else if (positions.x < this.lastX) {
if (this.frame >= 0 && this.frame - 1 > 0) {
this.frame -= 1;
} else if (this.loop) {
this.frame = this.images.length;
}
}
}
},
watch: {
zoomLevel: function() {
if (this.zoomLevel !== 1 && this.animationRequestID !== 0) {
this.spinStop();
}
}
},
computed: {
closestZoom: function() {
return this.zoomLevels.reduce((a, b) => {
return Math.abs(b - this.zoomLevel) < Math.abs(a - this.zoomLevel) ? b : a;
});
},
imageSet: function() {
return this.images.map(image => {
return image[this.closestZoom].url;
});
},
preloadProgress: function() {
return Math.floor(this.imagesPreloaded / this.images.length * 100);
},
currentPath: function() {
return this.images[this.frame - 1][this.closestZoom].url;
},
nextZoomLevel: function() {
if (this.zoomLevels.indexOf(this.closestZoom) === this.zoomLevels.length - 1) {
return this.zoomLevels[0];
}
return this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + 1];
},
viewportTransform: function() {
if (this.viewportEnabled) {
let translateX = -((this.translateX * this.viewportScale) * this.zoomLevel);
let translateY = -((this.translateY * this.viewportScale) * this.zoomLevel);
return `scale(${1 / this.zoomLevel}) translateX(${translateX}px) translateY(${translateY}px)`;
}
},
transform: function() {
return `scale(${this.zoomLevel}) translateX(${this.translateX}px) translateY(${this.translateY}px)`;
},
canZoomIn: function() {
return this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + 1] === undefined
},
canZoomOut: function() {
return this.zoomLevels[this.zoomLevels.indexOf(this.closestZoom) + -1] === undefined
}
},
template: '#template'
});
window.vue = new Vue({}).$mount('#app');
.media-360-viewer {
position: relative;
overflow: hidden;
display: inline-block;
background: #000;
width: 100%;
transition: filter .2s ease-in-out;
&__image {
width: 100%;
cursor: grab;
&.isTranslating {
cursor: grabbing;
}
&.loading {
filter: blur(4px);
}
}
&__loader {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .5);
* {
user-select: none;
}
&>svg {
width: 100%;
height: 100%;
transform: rotate(270deg);
}
&--text {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
p {
font-size: 100%;
font-weight: bold;
color: #fff;
&.large {
font-size: 150%;
}
}
}
&--background {
stroke-dasharray: 0;
stroke-dashoffset: 0;
stroke: rgba(0, 0, 0, .7);
stroke-width: 25px;
}
&--cover {
stroke-dasharray: 200%;
stroke: #848484;
stroke-width: 15px;
stroke-linecap: round;
}
&--background,
&--cover {
fill: transparent;
}
}
&__viewport {
position: absolute;
top: 10px;
left: 10px;
z-index: 2;
overflow: hidden;
&--image {
width: 100%;
pointer-events: none;
}
&--zoom {
position: absolute;
bottom: 5px;
right: 5px;
color: #fff;
z-index: 3;
font-size: 12px;
pointer-events: none;
}
&--square {
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
box-shadow: rgba(0, 0, 0, .6) 0 0 0 10000px;
cursor: grab;
transition: background ease-in-out .1s;
&:hover {
background: rgba(255, 255, 255, .2);
}
}
}
&__tools {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 10px;
&>a {
margin: 0 5px;
color: #000;
background: #fff;
border-radius: 50%;
width: 40px;
text-align: center;
line-height: 40px;
&[disabled] {
opacity: .5;
cursor: not-allowed;
&:hover {
color: #000;
background: #fff;
}
}
&:hover {
background: #000;
color: #fff;
}
}
&--autoplay {
&:before {
font-family: 'ClickIcons';
content: '\ea81';
}
&.active:before {
content: '\eb48';
}
}
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<test class="test"></test>
</div>
<script type="text/x-template" id="template">
<div>
<div class="media-360-viewer" ref="container">
<img tabindex="1" ref="image" draggable="false" src="https://s3-eu-west-1.amazonaws.com/crash.net/visordown.com/styles/amp_1200/s3/2020_YAM_YZF1000R1SPL_EU_BWM2_STA_001-70560.jpg?itok=5bisLKmj" :style="{ transform: transform }" class="media-360-viewer__image"
#touchend="handleEnd" #touchmove="handleMove" #touchstart="handleStart" #wheel="zoomWheel" alt="360 Image" />
</div>
</div>
</script>
I would like to make the face of this snake an image. Currently, it using a fill style with a color but I would like it to be an image. How can I do it with this code?
In addition, I want to find out how to add arrows so that it could work on a mobile phone. Thank you for anyone who can help or provide insight.
(function() {
/////////////////////////////////////////////////////////////
// Canvas & Context
var canvas;
var ctx;
// Snake
var snake;
var snake_dir;
var snake_next_dir;
var snake_speed;
// Food
var food = {
x: 0,
y: 0
};
// Score
var score;
// Wall
var wall;
// HTML Elements
var screen_snake;
var screen_menu;
var screen_setting;
var screen_gameover;
var button_newgame_menu;
var button_newgame_setting;
var button_newgame_gameover;
var button_setting_menu;
var button_setting_gameover;
var ele_score;
var speed_setting;
var wall_setting;
/////////////////////////////////////////////////////////////
var activeDot = function(x, y) {
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(x * 10, y * 10, 10, 10);
}
/////////////////////////////////////////////////////////////
var changeDir = function(key) {
if (key == 38 && snake_dir != 2) {
snake_next_dir = 0;
} else {
if (key == 39 && snake_dir != 3) {
snake_next_dir = 1;
} else {
if (key == 40 && snake_dir != 0) {
snake_next_dir = 2;
} else {
if (key == 37 && snake_dir != 1) {
snake_next_dir = 3;
}
}
}
}
}
/////////////////////////////////////////////////////////////
var addFood = function() {
food.x = Math.floor(Math.random() * ((canvas.width / 10) - 1));
food.y = Math.floor(Math.random() * ((canvas.height / 10) - 1));
for (var i = 0; i < snake.length; i++) {
if (checkBlock(food.x, food.y, snake[i].x, snake[i].y)) {
addFood();
}
}
}
/////////////////////////////////////////////////////////////
var checkBlock = function(x, y, _x, _y) {
return (x == _x && y == _y) ? true : false;
}
/////////////////////////////////////////////////////////////
var altScore = function(score_val) {
ele_score.innerHTML = String(score_val);
}
/////////////////////////////////////////////////////////////
var mainLoop = function() {
var _x = snake[0].x;
var _y = snake[0].y;
snake_dir = snake_next_dir;
// 0 - Up, 1 - Right, 2 - Down, 3 - Left
switch (snake_dir) {
case 0:
_y--;
break;
case 1:
_x++;
break;
case 2:
_y++;
break;
case 3:
_x--;
break;
}
snake.pop();
snake.unshift({
x: _x,
y: _y
});
// --------------------
// Wall
if (wall == 1) {
// On
if (snake[0].x < 0 || snake[0].x == canvas.width / 10 || snake[0].y < 0 || snake[0].y == canvas.height / 10) {
showScreen(3);
return;
}
} else {
// Off
for (var i = 0, x = snake.length; i < x; i++) {
if (snake[i].x < 0) {
snake[i].x = snake[i].x + (canvas.width / 10);
}
if (snake[i].x == canvas.width / 10) {
snake[i].x = snake[i].x - (canvas.width / 10);
}
if (snake[i].y < 0) {
snake[i].y = snake[i].y + (canvas.height / 10);
}
if (snake[i].y == canvas.height / 10) {
snake[i].y = snake[i].y - (canvas.height / 10);
}
}
}
// --------------------
// Autophagy death
for (var i = 1; i < snake.length; i++) {
if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
showScreen(3);
return;
}
}
// --------------------
// Eat Food
if (checkBlock(snake[0].x, snake[0].y, food.x, food.y)) {
snake[snake.length] = {
x: snake[0].x,
y: snake[0].y
};
score += 1;
altScore(score);
addFood();
activeDot(food.x, food.y);
}
// --------------------
ctx.beginPath();
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// --------------------
for (var i = 0; i < snake.length; i++) {
activeDot(snake[i].x, snake[i].y);
}
// --------------------
activeDot(food.x, food.y);
// Debug
//document.getElementById("debug").innerHTML = snake_dir + " " + snake_next_dir + " " + snake[0].x + " " + snake[0].y;
setTimeout(mainLoop, snake_speed);
}
/////////////////////////////////////////////////////////////
var newGame = function() {
showScreen(0);
screen_snake.focus();
snake = [];
for (var i = 4; i >= 0; i--) {
snake.push({
x: i,
y: 15
});
}
snake_next_dir = 1;
score = 0;
altScore(score);
addFood();
canvas.onkeydown = function(evt) {
evt = evt || window.event;
changeDir(evt.keyCode);
}
mainLoop();
}
/////////////////////////////////////////////////////////////
// Change the snake speed...
// 150 = slow
// 100 = normal
// 50 = fast
var setSnakeSpeed = function(speed_value) {
snake_speed = speed_value;
}
/////////////////////////////////////////////////////////////
var setWall = function(wall_value) {
wall = wall_value;
if (wall == 0) {
screen_snake.style.borderColor = "#606060";
}
if (wall == 1) {
screen_snake.style.borderColor = "#FFFFFF";
}
}
/////////////////////////////////////////////////////////////
// 0 for the game
// 1 for the main menu
// 2 for the settings screen
// 3 for the game over screen
var showScreen = function(screen_opt) {
switch (screen_opt) {
case 0:
screen_snake.style.display = "block";
screen_menu.style.display = "none";
screen_setting.style.display = "none";
screen_gameover.style.display = "none";
break;
case 1:
screen_snake.style.display = "none";
screen_menu.style.display = "block";
screen_setting.style.display = "none";
screen_gameover.style.display = "none";
break;
case 2:
screen_snake.style.display = "none";
screen_menu.style.display = "none";
screen_setting.style.display = "block";
screen_gameover.style.display = "none";
break;
case 3:
screen_snake.style.display = "none";
screen_menu.style.display = "none";
screen_setting.style.display = "none";
screen_gameover.style.display = "block";
break;
}
}
/////////////////////////////////////////////////////////////
window.onload = function() {
canvas = document.getElementById("snake");
ctx = canvas.getContext("2d");
// Screens
screen_snake = document.getElementById("snake");
screen_menu = document.getElementById("menu");
screen_gameover = document.getElementById("gameover");
screen_setting = document.getElementById("setting");
// Buttons
button_newgame_menu = document.getElementById("newgame_menu");
button_newgame_setting = document.getElementById("newgame_setting");
button_newgame_gameover = document.getElementById("newgame_gameover");
button_setting_menu = document.getElementById("setting_menu");
button_setting_gameover = document.getElementById("setting_gameover");
// etc
ele_score = document.getElementById("score_value");
speed_setting = document.getElementsByName("speed");
wall_setting = document.getElementsByName("wall");
// --------------------
button_newgame_menu.onclick = function() {
newGame();
};
button_newgame_gameover.onclick = function() {
newGame();
};
button_newgame_setting.onclick = function() {
newGame();
};
button_setting_menu.onclick = function() {
showScreen(2);
};
button_setting_gameover.onclick = function() {
showScreen(2)
};
setSnakeSpeed(150);
setWall(1);
showScreen("menu");
// --------------------
// Settings
// speed
for (var i = 0; i < speed_setting.length; i++) {
speed_setting[i].addEventListener("click", function() {
for (var i = 0; i < speed_setting.length; i++) {
if (speed_setting[i].checked) {
setSnakeSpeed(speed_setting[i].value);
}
}
});
}
// wall
for (var i = 0; i < wall_setting.length; i++) {
wall_setting[i].addEventListener("click", function() {
for (var i = 0; i < wall_setting.length; i++) {
if (wall_setting[i].checked) {
setWall(wall_setting[i].value);
}
}
});
}
document.onkeydown = function(evt) {
if (screen_gameover.style.display == "block") {
evt = evt || window.event;
if (evt.keyCode == 32) {
newGame();
}
}
}
}
})();
::selection {
color: #FFFFFF;
background: transparent;
}
::-moz-selection {
color: #FFFFFF;
background: transparent;
}
* {
margin: 0;
padding: 0;
font-family: "VT323";
}
body {
background-color: #000000;
}
.wrap {
margin-left: auto;
margin-right: auto;
}
header {
width: 340px;
font-size: 0;
}
canvas {
display: none;
border-style: solid;
border-width: 10px;
border-color: #FFFFFF;
}
canvas:focus {
outline: none;
}
/* Top Styles */
h1 {
display: inline-block;
width: 100px;
font-size: 32px;
color: #FFFFFF;
}
.score {
display: inline-block;
width: 240px;
font-size: 20px;
color: #FFFFFF;
text-align: right;
}
.score_value {
font-size: inherit;
}
/* All screens style */
#gameover a,
#setting a,
#menu a {
display: block;
}
#gameover a,
#setting a:hover,
#menu a:hover {
cursor: pointer;
}
#gameover a:hover::before,
#setting a:hover::before,
#menu a:hover::before {
content: ">";
margin-right: 10px;
}
/* Menu Screen Style */
#menu {
display: block;
width: 340px;
padding-top: 95px;
padding-bottom: 95px;
font-size: 40px;
margin-left: auto;
margin-right: auto;
text-align: center;
color: #FFF;
}
#menu h2 {
-webkit-animation: logo-ani 1000ms linear infinite;
animation: logo-ani 1000ms linear infinite;
margin-bottom: 30px;
}
#menu a {
font-size: 30px;
}
#-webkit-keyframes logo-ani {
50% {
-webkit-transform: scale(1.3, 1.3);
}
100% {
-webkit-transform: scale(1.0, 1.0);
}
}
#keyframes logo-ani {
50% {
transform: scale(1.3, 1.3);
}
100% {
transform: scale(1.0, 1.0);
}
}
/* Game Over Screen Style */
#gameover {
display: none;
width: 340px;
padding-top: 95px;
padding-bottom: 95px;
margin-left: auto;
margin-right: auto;
text-align: center;
font-size: 30px;
color: #FFF;
}
#gameover p {
margin-top: 25px;
font-size: 20px;
}
/* Settings Screen Style */
#setting {
display: none;
width: 340px;
margin-left: auto;
margin-right: auto;
padding-top: 85px;
padding-bottom: 85px;
font-size: 30px;
color: #FFF;
text-align: center;
}
#setting h2 {
margin-bottom: 15px;
}
#setting p {
margin-top: 10px;
}
#setting input {
display: none;
}
#setting label {
cursor: pointer;
}
#setting input:checked+label {
background-color: #FFF;
color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
<header class="wrap">
<h1>Snake</h1>
<p class="score">Score: <span id="score_value">0</span></p>
</header>
<canvas class="wrap" id="snake" width="320" height="320" tabindex="1"></canvas>
<!-- Game Over Screen -->
<div id="gameover">
<h2>Game Over</h2>
<p>press <span style="background-color: #FFFFFF; color: #000000">space</span> to begin a</p>
<a id="newgame_gameover">new game</a>
<a id="setting_gameover">settings</a>
</div>
<!-- Setting screen -->
<div id="setting">
<h2>Settings</h2>
<a id="newgame_setting">new game</a>
<p>Speed:
<input id="speed1" type="radio" name="speed" value="120" checked/>
<label for="speed1">Slow</label>
<input id="speed2" type="radio" name="speed" value="75" />
<label for="speed2">Normal</label>
<input id="speed3" type="radio" name="speed" value="35" />
<label for="speed3">Fast</label>
</p>
<p>Wall:
<input id="wallon" type="radio" name="wall" value="1" checked/>
<label for="wallon">On</label>
<input id="walloff" type="radio" name="wall" value="0" />
<label for="walloff">Off</label>
</p>
</div>
<!-- Main Menu Screen -->
<div id="menu">
<h2>Snake</h2>
<a id="newgame_menu">new game</a>
<a id="setting_menu">settings</a>
</div>
Convert your image to a base64 string, then for the first dot/head use the image instead:
var img = new Image(); // Create new img element
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA21BMVEXoTTvqTTzpUD7nTjzmTTvrUkDpTjzmSznUPSrVPCrnTDrSOSfTOizlTDrvoJnoqJ/pVkTmU0P5urH1p53mSTjjPiv7nZF0f4NZaGvpn5b9s6qDl5iira/+nI/jPirkPyz7lop+iYtleHzsnpT7raOTpqqqtbf4lovnSjf0lorylonpSDbnTDj5oZf2mIzlSDXkOyjIY1vrd2rrWEbZZ1zYQDLsTTroTz/lRjPalY7+///////j19fVSz7tTjvmTjntRjPialzZhH3sVkXsSzniRTTYQTDmSTbmTT3qb45jAAAAAWJLR0Q7OQ70bAAAAAd0SU1FB+QEDw4AEYzMSFoAAABvSURBVAjXY2BgZGJiZmFlZWNgYGDn4GTn4ubhBTJZ+PgFBIWERdgYRMXEJSSlpGVk5RjkFRSVlFVU1dTlGRg0NLW0dXT19JkZGNgMDI2MTUzNgNrMLSytrG1s7eyBbGYHRydnFwYwYHN1c/dgYAAAtKsKjnGo4BwAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDQtMTVUMTQ6MDA6MTctMDQ6MDAVi7z/AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTA0LTE1VDE0OjAwOjE3LTA0OjAwZNYEQwAAAABJRU5ErkJggg==";
for (var i = 0; i < snake.length; i++) {
if (!i) {
ctx.drawImage(img, snake[i].x * 10, snake[i].y * 10);
} else {
activeDot(snake[i].x, snake[i].y);
}
}
I want to apply magnifying glass and lightbox both on an image so when a user hovers on an image the glass effect will appear and when he clicks the lightbox will appear. But in my case the lightbox stopped working when I actived the magnifying glass. So when I remove the glass CSS lightbox worked normally.
/*!
* Lightbox v2.10.0
* by Lokesh Dhakar
*
* More info:
* http://lokeshdhakar.com/projects/lightbox2/
*
* Copyright 2007, 2018 Lokesh Dhakar
* Released under the MIT license
* https://github.com/lokesh/lightbox2/blob/master/LICENSE
*
* #preserve
*/
! function(a, b) {
"function" == typeof define && define.amd ? define(["jquery"], b) : "object" == typeof exports ? module.exports = b(require("jquery")) : a.lightbox = b(a.jQuery)
}(this, function(a) {
function b(b) {
this.album = [], this.currentImageIndex = void 0, this.init(), this.options = a.extend({}, this.constructor.defaults), this.option(b)
}
return b.defaults = {
albumLabel: "Image %1 of %2",
alwaysShowNavOnTouchDevices: !1,
fadeDuration: 600,
fitImagesInViewport: !0,
imageFadeDuration: 600,
positionFromTop: 50,
resizeDuration: 700,
showImageNumberLabel: !0,
wrapAround: !1,
disableScrolling: !1,
sanitizeTitle: !1
}, b.prototype.option = function(b) {
a.extend(this.options, b)
}, b.prototype.imageCountLabel = function(a, b) {
return this.options.albumLabel.replace(/%1/g, a).replace(/%2/g, b)
}, b.prototype.init = function() {
var b = this;
a(document).ready(function() {
b.enable(), b.build()
})
}, b.prototype.enable = function() {
var b = this;
a("body").on("click", "a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]", function(c) {
return b.start(a(c.currentTarget)), !1
})
}, b.prototype.build = function() {
if (!(a("#lightbox").length > 0)) {
var b = this;
a('<div id="lightboxOverlay" class="lightboxOverlay"></div><div id="lightbox" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" /><div class="lb-nav"><a class="lb-prev" href="" ></a><a class="lb-next" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo(a("body")), this.$lightbox = a("#lightbox"), this.$overlay = a("#lightboxOverlay"), this.$outerContainer = this.$lightbox.find(".lb-outerContainer"), this.$container = this.$lightbox.find(".lb-container"), this.$image = this.$lightbox.find(".lb-image"), this.$nav = this.$lightbox.find(".lb-nav"), this.containerPadding = {
top: parseInt(this.$container.css("padding-top"), 10),
right: parseInt(this.$container.css("padding-right"), 10),
bottom: parseInt(this.$container.css("padding-bottom"), 10),
left: parseInt(this.$container.css("padding-left"), 10)
}, this.imageBorderWidth = {
top: parseInt(this.$image.css("border-top-width"), 10),
right: parseInt(this.$image.css("border-right-width"), 10),
bottom: parseInt(this.$image.css("border-bottom-width"), 10),
left: parseInt(this.$image.css("border-left-width"), 10)
}, this.$overlay.hide().on("click", function() {
return b.end(), !1
}), this.$lightbox.hide().on("click", function(c) {
return "lightbox" === a(c.target).attr("id") && b.end(), !1
}), this.$outerContainer.on("click", function(c) {
return "lightbox" === a(c.target).attr("id") && b.end(), !1
}), this.$lightbox.find(".lb-prev").on("click", function() {
return 0 === b.currentImageIndex ? b.changeImage(b.album.length - 1) : b.changeImage(b.currentImageIndex - 1), !1
}), this.$lightbox.find(".lb-next").on("click", function() {
return b.currentImageIndex === b.album.length - 1 ? b.changeImage(0) : b.changeImage(b.currentImageIndex + 1), !1
}), this.$nav.on("mousedown", function(a) {
3 === a.which && (b.$nav.css("pointer-events", "none"), b.$lightbox.one("contextmenu", function() {
setTimeout(function() {
this.$nav.css("pointer-events", "auto")
}.bind(b), 0)
}))
}), this.$lightbox.find(".lb-loader, .lb-close").on("click", function() {
return b.end(), !1
})
}
}, b.prototype.start = function(b) {
function c(a) {
d.album.push({
alt: a.attr("data-alt"),
link: a.attr("href"),
title: a.attr("data-title") || a.attr("title")
})
}
var d = this,
e = a(window);
e.on("resize", a.proxy(this.sizeOverlay, this)), a("select, object, embed").css({
visibility: "hidden"
}), this.sizeOverlay(), this.album = [];
var f, g = 0,
h = b.attr("data-lightbox");
if (h) {
f = a(b.prop("tagName") + '[data-lightbox="' + h + '"]');
for (var i = 0; i < f.length; i = ++i) c(a(f[i])), f[i] === b[0] && (g = i)
} else if ("lightbox" === b.attr("rel")) c(b);
else {
f = a(b.prop("tagName") + '[rel="' + b.attr("rel") + '"]');
for (var j = 0; j < f.length; j = ++j) c(a(f[j])), f[j] === b[0] && (g = j)
}
var k = e.scrollTop() + this.options.positionFromTop,
l = e.scrollLeft();
this.$lightbox.css({
top: k + "px",
left: l + "px"
}).fadeIn(this.options.fadeDuration), this.options.disableScrolling && a("html").addClass("lb-disable-scrolling"), this.changeImage(g)
}, b.prototype.changeImage = function(b) {
var c = this;
this.disableKeyboardNav();
var d = this.$lightbox.find(".lb-image");
this.$overlay.fadeIn(this.options.fadeDuration), a(".lb-loader").fadeIn("slow"), this.$lightbox.find(".lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption").hide(), this.$outerContainer.addClass("animating");
var e = new Image;
e.onload = function() {
var f, g, h, i, j, k;
d.attr({
alt: c.album[b].alt,
src: c.album[b].link
}), a(e), d.width(e.width), d.height(e.height), c.options.fitImagesInViewport && (k = a(window).width(), j = a(window).height(), i = k - c.containerPadding.left - c.containerPadding.right - c.imageBorderWidth.left - c.imageBorderWidth.right - 20, h = j - c.containerPadding.top - c.containerPadding.bottom - c.imageBorderWidth.top - c.imageBorderWidth.bottom - 120, c.options.maxWidth && c.options.maxWidth < i && (i = c.options.maxWidth), c.options.maxHeight && c.options.maxHeight < i && (h = c.options.maxHeight), (e.width > i || e.height > h) && (e.width / i > e.height / h ? (g = i, f = parseInt(e.height / (e.width / g), 10), d.width(g), d.height(f)) : (f = h, g = parseInt(e.width / (e.height / f), 10), d.width(g), d.height(f)))), c.sizeContainer(d.width(), d.height())
}, e.src = this.album[b].link, this.currentImageIndex = b
}, b.prototype.sizeOverlay = function() {
this.$overlay.width(a(document).width()).height(a(document).height())
}, b.prototype.sizeContainer = function(a, b) {
function c() {
d.$lightbox.find(".lb-dataContainer").width(g), d.$lightbox.find(".lb-prevLink").height(h), d.$lightbox.find(".lb-nextLink").height(h), d.showImage()
}
var d = this,
e = this.$outerContainer.outerWidth(),
f = this.$outerContainer.outerHeight(),
g = a + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right,
h = b + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
e !== g || f !== h ? this.$outerContainer.animate({
width: g,
height: h
}, this.options.resizeDuration, "swing", function() {
c()
}) : c()
}, b.prototype.showImage = function() {
this.$lightbox.find(".lb-loader").stop(!0).hide(), this.$lightbox.find(".lb-image").fadeIn(this.options.imageFadeDuration), this.updateNav(), this.updateDetails(), this.preloadNeighboringImages(), this.enableKeyboardNav()
}, b.prototype.updateNav = function() {
var a = !1;
try {
document.createEvent("TouchEvent"), a = !!this.options.alwaysShowNavOnTouchDevices
} catch (a) {}
this.$lightbox.find(".lb-nav").show(), this.album.length > 1 && (this.options.wrapAround ? (a && this.$lightbox.find(".lb-prev, .lb-next").css("opacity", "1"), this.$lightbox.find(".lb-prev, .lb-next").show()) : (this.currentImageIndex > 0 && (this.$lightbox.find(".lb-prev").show(), a && this.$lightbox.find(".lb-prev").css("opacity", "1")), this.currentImageIndex < this.album.length - 1 && (this.$lightbox.find(".lb-next").show(), a && this.$lightbox.find(".lb-next").css("opacity", "1"))))
}, b.prototype.updateDetails = function() {
var b = this;
if (void 0 !== this.album[this.currentImageIndex].title && "" !== this.album[this.currentImageIndex].title) {
var c = this.$lightbox.find(".lb-caption");
this.options.sanitizeTitle ? c.text(this.album[this.currentImageIndex].title) : c.html(this.album[this.currentImageIndex].title), c.fadeIn("fast").find("a").on("click", function(b) {
void 0 !== a(this).attr("target") ? window.open(a(this).attr("href"), a(this).attr("target")) : location.href = a(this).attr("href")
})
}
if (this.album.length > 1 && this.options.showImageNumberLabel) {
var d = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
this.$lightbox.find(".lb-number").text(d).fadeIn("fast")
} else this.$lightbox.find(".lb-number").hide();
this.$outerContainer.removeClass("animating"), this.$lightbox.find(".lb-dataContainer").fadeIn(this.options.resizeDuration, function() {
return b.sizeOverlay()
})
}, b.prototype.preloadNeighboringImages = function() {
if (this.album.length > this.currentImageIndex + 1) {
(new Image).src = this.album[this.currentImageIndex + 1].link
}
if (this.currentImageIndex > 0) {
(new Image).src = this.album[this.currentImageIndex - 1].link
}
}, b.prototype.enableKeyboardNav = function() {
a(document).on("keyup.keyboard", a.proxy(this.keyboardAction, this))
}, b.prototype.disableKeyboardNav = function() {
a(document).off(".keyboard")
}, b.prototype.keyboardAction = function(a) {
var b = a.keyCode,
c = String.fromCharCode(b).toLowerCase();
27 === b || c.match(/x|o|c/) ? this.end() : "p" === c || 37 === b ? 0 !== this.currentImageIndex ? this.changeImage(this.currentImageIndex - 1) : this.options.wrapAround && this.album.length > 1 && this.changeImage(this.album.length - 1) : "n" !== c && 39 !== b || (this.currentImageIndex !== this.album.length - 1 ? this.changeImage(this.currentImageIndex + 1) : this.options.wrapAround && this.album.length > 1 && this.changeImage(0))
}, b.prototype.end = function() {
this.disableKeyboardNav(), a(window).off("resize", this.sizeOverlay), this.$lightbox.fadeOut(this.options.fadeDuration), this.$overlay.fadeOut(this.options.fadeDuration), a("select, object, embed").css({
visibility: "visible"
}), this.options.disableScrolling && a("html").removeClass("lb-disable-scrolling")
}, new b
});
//# sourceMappingURL=lightbox.min.map
//magnyfing glass
$(function() {
var native_width = 0;
var native_height = 0;
var mouse = {
x: 0,
y: 0
};
var magnify;
var cur_img;
var ui = {
magniflier: $('.magniflier')
};
// Add the magnifying glass
if (ui.magniflier.length) {
var div = document.createElement('div');
div.setAttribute('class', 'glass');
ui.glass = $(div);
$('body').append(div);
}
// All the magnifying will happen on "mousemove"
var mouseMove = function(e) {
var $el = $(this);
// Container offset relative to document
var magnify_offset = cur_img.offset();
// Mouse position relative to container
// pageX/pageY - container's offsetLeft/offetTop
mouse.x = e.pageX - magnify_offset.left;
mouse.y = e.pageY - magnify_offset.top;
// The Magnifying glass should only show up when the mouse is inside
// It is important to note that attaching mouseout and then hiding
// the glass wont work cuz mouse will never be out due to the glass
// being inside the parent and having a higher z-index (positioned above)
if (
mouse.x < cur_img.width() &&
mouse.y < cur_img.height() &&
mouse.x > 0 &&
mouse.y > 0
) {
magnify(e);
} else {
ui.glass.fadeOut(100);
}
return;
};
var magnify = function(e) {
// The background position of div.glass will be
// changed according to the position
// of the mouse over the img.magniflier
//
// So we will get the ratio of the pixel
// under the mouse with respect
// to the image and use that to position the
// large image inside the magnifying glass
var rx = Math.round(mouse.x / cur_img.width() * native_width - ui.glass.width() / 2) * -1;
var ry = Math.round(mouse.y / cur_img.height() * native_height - ui.glass.height() / 2) * -1;
var bg_pos = rx + "px " + ry + "px";
// Calculate pos for magnifying glass
//
// Easy Logic: Deduct half of width/height
// from mouse pos.
// var glass_left = mouse.x - ui.glass.width() / 2;
// var glass_top = mouse.y - ui.glass.height() / 2;
var glass_left = e.pageX - ui.glass.width() / 2;
var glass_top = e.pageY - ui.glass.height() / 2;
//console.log(glass_left, glass_top, bg_pos)
// Now, if you hover on the image, you should
// see the magnifying glass in action
ui.glass.css({
left: glass_left,
top: glass_top,
backgroundPosition: bg_pos
});
return;
};
$('.magniflier').on('mousemove', function() {
ui.glass.fadeIn(200);
cur_img = $(this);
var large_img_loaded = cur_img.data('large-img-loaded');
var src = cur_img.data('large') || cur_img.attr('src');
// Set large-img-loaded to true
// cur_img.data('large-img-loaded', true)
if (src) {
ui.glass.css({
'background-image': 'url(' + src + ')',
'background-repeat': 'no-repeat'
});
}
// When the user hovers on the image, the script will first calculate
// the native dimensions if they don't exist. Only after the native dimensions
// are available, the script will show the zoomed version.
//if(!native_width && !native_height) {
if (!cur_img.data('native_width')) {
// This will create a new image object with the same image as that in .small
// We cannot directly get the dimensions from .small because of the
// width specified to 200px in the html. To get the actual dimensions we have
// created this image object.
var image_object = new Image();
image_object.onload = function() {
// This code is wrapped in the .load function which is important.
// width and height of the object would return 0 if accessed before
// the image gets loaded.
native_width = image_object.width;
native_height = image_object.height;
cur_img.data('native_width', native_width);
cur_img.data('native_height', native_height);
//console.log(native_width, native_height);
mouseMove.apply(this, arguments);
ui.glass.on('mousemove', mouseMove);
};
image_object.src = src;
return;
} else {
native_width = cur_img.data('native_width');
native_height = cur_img.data('native_height');
}
//}
//console.log(native_width, native_height);
mouseMove.apply(this, arguments);
ui.glass.on('mousemove', mouseMove);
});
ui.glass.on('mouseout', function() {
ui.glass.off('mousemove', mouseMove);
});
});
html.lb-disable-scrolling {
overflow: hidden;
/* Position fixed required for iOS. Just putting overflow: hidden; on the body is not enough. */
position: fixed;
height: 100vh;
width: 100vw;
}
.lightboxOverlay {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
background-color: black;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
opacity: 0.8;
display: none;
}
.lightbox {
position: absolute;
left: 0;
width: 100%;
z-index: 10000;
text-align: center;
line-height: 0;
font-weight: normal;
}
.lightbox .lb-image {
display: block;
height: auto;
max-width: inherit;
max-height: none;
border-radius: 3px;
/* Image border */
border: 4px solid white;
}
.lightbox a img {
border: none;
}
.lb-outerContainer {
position: relative;
*zoom: 1;
width: 250px;
height: 250px;
margin: 0 auto;
border-radius: 4px;
/* Background color behind image.
This is visible during transitions. */
background-color: white;
}
.lb-outerContainer:after {
content: "";
display: table;
clear: both;
}
.lb-loader {
position: absolute;
top: 43%;
left: 0;
height: 25%;
width: 100%;
text-align: center;
line-height: 0;
}
.lb-cancel {
display: block;
width: 32px;
height: 32px;
margin: 0 auto;
background: url(../assets/imgs/lightbox/loading.gif) no-repeat;
}
.lb-nav {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 10;
}
.lb-container>.nav {
left: 0;
}
.lb-nav a {
outline: none;
background-image: url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
}
.lb-prev,
.lb-next {
height: 100%;
cursor: pointer;
display: block;
}
.lb-nav a.lb-prev {
width: 34%;
left: 0;
float: left;
background: url(../assets/imgs/lightbox/prev.png) left 48% no-repeat;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
opacity: 0;
-webkit-transition: opacity 0.6s;
-moz-transition: opacity 0.6s;
-o-transition: opacity 0.6s;
transition: opacity 0.6s;
}
.lb-nav a.lb-prev:hover {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}
.lb-nav a.lb-next {
width: 64%;
right: 0;
float: right;
background: url(../assets/imgs/lightbox/next.png) right 48% no-repeat;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
opacity: 0;
-webkit-transition: opacity 0.6s;
-moz-transition: opacity 0.6s;
-o-transition: opacity 0.6s;
transition: opacity 0.6s;
}
.lb-nav a.lb-next:hover {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}
.lb-dataContainer {
margin: 0 auto;
padding-top: 5px;
*zoom: 1;
width: 100%;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.lb-dataContainer:after {
content: "";
display: table;
clear: both;
}
.lb-data {
padding: 0 4px;
color: #ccc;
}
.lb-data .lb-details {
width: 85%;
float: left;
text-align: left;
line-height: 1.1em;
}
.lb-data .lb-caption {
font-size: 13px;
font-weight: bold;
line-height: 1em;
}
.lb-data .lb-caption a {
color: #4ae;
}
.lb-data .lb-number {
display: block;
clear: left;
padding-bottom: 1em;
font-size: 12px;
color: #999999;
}
.lb-data .lb-close {
display: block;
float: right;
width: 30px;
height: 30px;
background: url(../assets/imgs/lightbox/close.png) top right no-repeat;
text-align: right;
outline: none;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=70);
opacity: 0.7;
-webkit-transition: opacity 0.2s;
-moz-transition: opacity 0.2s;
-o-transition: opacity 0.2s;
transition: opacity 0.2s;
}
.lb-data .lb-close:hover {
cursor: pointer;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
opacity: 1;
}
/* IF you remove this, lightbox will work but not the magnyfing glass */
.glass {
width: 150px;
height: 150px;
position: absolute;
border-radius: 50%;
cursor: crosshair;
/* Multiple box shadows to achieve the glass effect */
box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85), 0 0 7px 7px rgba(0, 0, 0, 0.25), inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
/* hide the glass by default */
display: none;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--START BOOK PREVIEW-->
<div class="book-preview px-5 py-5 container img-magnifier-container">
<div class="row">
<div class="col-lg-4 book">
<a href="https://subsolardesigns.com/odrin/demo1/wp-content/uploads/sites/8/2017/08/cover_taurus-468x700.png" data-lightbox="image-1" data-title="My caption">
<img src="https://subsolardesigns.com/odrin/demo1/wp-content/uploads/sites/8/2017/08/cover_taurus-468x700.png" alt="Book" class="img-fluid magniflier" id="book-glass" alt="Responsive image">
</a>
</div>
</div>
</div>
The issue is that you are not clicking the image, but the .glass dom node. You need to handle the click event on the .glass element and then call click on the image, in order for the lightbox plugin to do what it expects to do. Add the code below to you javascript to redirect the click event to your image tag.
ui.glass.on('click', function() {
cur_img.click();
});
Here is a link to the website so that you can visualize the error im expressing in my title:
https://glassesled.com/aubrey
If you hover over the picture the zoom box doesn't follow the cursor and when you go the lower portions of the image the zoom box reaches a wall. Here are the relevant files (the ones I think are relevant)
The CloudZoom.min.js file
//////////////////////////////////////////////////////////////////////////////////
// Cloud Zoom V1.0.2
// (c) 2010 by R Cecco. <http://www.professorcloud.com>
// MIT License
//
// Please retain this copyright header in all versions of the software
//////////////////////////////////////////////////////////////////////////////////
! function($) {
function format(t) {
for (var o = 1; o < arguments.length; o++) t = t.replace("%" + (o - 1), arguments[o]);
return t
}
function CloudZoom(t, o) {
var e, i, s, a, n, r, l, d, u = $("img", t),
p = null,
c = null,
h = null,
m = null,
f = null,
g = null,
v = 0,
x = 0,
b = 0,
y = 0,
z = 0,
w = 0,
O = this;
setTimeout(function() {
if (null === c) {
var o = t.width();
t.parent().append(format('<div style="width:%0px;position:absolute;top:75%;left:%1px;text-align:center" class="cloud-zoom-loading" >Loading...</div>', o / 3, o / 2 - o / 6)).find(":last").css("opacity", .5)
}
}, 200);
var k = function() {
null !== g && (g.remove(), g = null)
};
this.removeBits = function() {
h && (h.remove(), h = null), m && (m.remove(), m = null), f && (f.remove(), f = null), k(), $(".cloud-zoom-loading", t.parent()).remove()
}, this.destroy = function() {
t.data("zoom", null), c && (c.unbind(), c.remove(), c = null), p && (p.remove(), p = null), this.removeBits()
}, this.fadedOut = function() {
p && (p.remove(), p = null), this.removeBits()
}, this.controlLoop = function() {
if (h) {
var t = r - u.offset().left - .5 * a >> 0,
e = l - u.offset().top - .5 * n >> 0;
0 > t ? t = 0 : t > u.outerWidth() - a && (t = u.outerWidth() - a), 0 > e ? e = 0 : e > u.outerHeight() - n && (e = u.outerHeight() - n), h.css({
left: t,
top: e
}), h.css("background-position", -t + "px " + -e + "px"), x = t / u.outerWidth() * s.width >> 0, b = e / u.outerHeight() * s.height >> 0, z += (x - z) / o.smoothMove, y += (b - y) / o.smoothMove, p.css("background-position", -(z >> 0) + "px " + (-(y >> 0) + "px"))
}
v = setTimeout(function() {
O.controlLoop()
}, 30)
}, this.init2 = function(t, o) {
w++, 1 === o && (s = t), 2 === w && this.init()
}, this.init = function() {
$(".cloud-zoom-loading", t.parent()).remove();
var e = $(".mousetrap");
e && e.remove(), c = $.browser.msie ? t.parent().append(format("<div class='mousetrap' style='background-image:url(\"/Plugins/SevenSpikes.Nop.Plugins.CloudZoom/Scripts/cloud-zoom.1.0.2/DummyPageForIE.htm\");z-index:999;position:absolute;width:%0px;height:%1px;left:%2px;top:%3px;'></div>", u.outerWidth(), u.outerHeight(), 0, 0)).find(":last") : t.parent().append(format("<div class='mousetrap' style='z-index:999;position:absolute;width:%0px;height:%1px;left:%2px;top:%3px;'></div>", u.outerWidth(), u.outerHeight(), 0, 0)).find(":last"), c.bind("mousemove", this, function(t) {
r = t.pageX, l = t.pageY
}), c.bind("mouseleave", this, function(t) {
return clearTimeout(v), h && h.fadeOut(299), m && m.fadeOut(299), f && f.fadeOut(299), p.fadeOut(300, function() {
O.fadedOut()
}), !1
}), c.bind("mouseenter", this, function(e) {
r = e.pageX, l = e.pageY, d = e.data, p && (p.stop(!0, !1), p.remove());
var i = o.adjustX,
v = o.adjustY,
x = u.outerWidth(),
b = u.outerHeight(),
y = o.zoomWidth,
z = o.zoomHeight;
"auto" == o.zoomWidth && (y = x), "auto" == o.zoomHeight && (z = b);
var w = t.parent();
switch (o.position) {
case "top":
v -= z;
break;
case "right":
i += x;
break;
case "bottom":
v += b;
break;
case "left":
i -= y;
break;
case "inside":
y = x, z = b;
break;
default:
w = $("#" + o.position), w.length ? (y = o.zoomWidth, z = o.zoomHeight) : (w = t, i += x, v += b)
}
p = w.append(format('<div id="cloud-zoom-big" class="cloud-zoom-big" style="display:none;position:absolute;left:%0px;top:%1px;width:%2px;height:%3px;background-image:url(\'%4\');z-index:99;"></div>', i, v, y, z, s.src)).find(":last"), u.attr("title") && o.showTitle && p.append(format('<div class="cloud-zoom-title">%0</div>', u.attr("title"))).find(":last").css("opacity", o.titleOpacity), $.browser.msie && $.browser.version < 7 && (g = $('<iframe frameborder="0" src="#"></iframe>').css({
position: "absolute",
left: i,
top: v,
zIndex: 99,
width: y,
height: z
}).insertBefore(p)), p.fadeIn(500), h && (h.remove(), h = null), a = u.outerWidth() / s.width * p.width(), n = u.outerHeight() / s.height * p.height(), h = t.append(format("<div class = 'cloud-zoom-lens' style='display:none;z-index:98;position:absolute;width:%0px;height:%1px;'></div>", a, n)).find(":last"), c.css("cursor", h.css("cursor"));
var O = !1;
o.tint && (h.css("background", 'url("' + u.attr("src") + '")'), m = t.append(format('<div class="cloud-zoom-tint" style="display:none;position:absolute; left:0px; top:0px; width:%0px; height:%1px; background-color:%2;" />', u.outerWidth(), u.outerHeight(), o.tint)).find(":last"), m.css("opacity", o.tintOpacity), O = !0, m.fadeIn(500)), o.softFocus && (h.css("background", 'url("' + u.attr("src") + '")'), f = t.append(format('<div class="cloud-zoom-softfocus" style="position:absolute;display:none;top:2px; left:2px; width:%0px; height:%1px;" />', u.outerWidth() - 2, u.outerHeight() - 2, o.tint)).find(":last"), f.css("background", 'url("' + u.attr("src") + '")'), f.css("opacity", .5), O = !0, f.fadeIn(500)), O || h.css("opacity", o.lensOpacity), "inside" !== o.position && h.fadeIn(500), d.controlLoop()
})
}, e = new Image, $(e).load(function() {
O.init2(this, 0)
}), e.src = u.attr("src"), i = new Image, $(i).load(function() {
O.init2(this, 1)
}), i.src = t.attr("href")
}
$(document).ready(function() {
$(".cloud-zoom, .cloud-zoom-gallery").CloudZoom()
}), $.fn.CloudZoom = function(options) {
try {
document.execCommand("BackgroundImageCache", !1, !0)
} catch (e) {}
return this.each(function() {
var relOpts, opts;
eval("var a = {" + $(this).attr("rel") + "}"), relOpts = a, $(this).is(".cloud-zoom") ? ($(this).css({
position: "relative",
display: "block"
}), $("img", $(this)).css({
display: "block"
}), "wrap" != $(this).parent().attr("id") && $(this).wrap('<div id="wrap" style="top:0px;position:relative;"></div>'), opts = $.extend({}, $.fn.CloudZoom.defaults, options), opts = $.extend({}, opts, relOpts), $(this).data("zoom", new CloudZoom($(this), opts))) : $(this).is(".cloud-zoom-gallery") && (opts = $.extend({}, relOpts, options), $(this).data("relOpts", opts), $(this).bind("click", $(this), function(t) {
var o = t.data.data("relOpts");
return $("#" + o.useZoom).data("zoom").destroy(), $("#" + o.useZoom).attr("href", t.data.attr("href")), $("#" + o.useZoom).attr("rel", t.data.attr("rel")), $("#" + o.useZoom + " img").attr("title", t.data.attr("title")), $("#" + o.useZoom + " img").attr("src", t.data.data("relOpts").smallImage), $("#" + t.data.data("relOpts").useZoom).CloudZoom(), !1
}))
}), this
}, $.fn.CloudZoom.defaults = {
zoomWidth: "auto",
zoomHeight: "auto",
position: "right",
tint: !1,
tintOpacity: .5,
lensOpacity: .5,
softFocus: !1,
smoothMove: 3,
showTitle: !0,
titleOpacity: .5,
adjustX: 0,
adjustY: 0
}
}(jQuery);
CSS file used in cshtml
/*
* Copyright 2014 Seven Spikes Ltd. All rights reserved. (http://www.nop-templates.com)
* http://www.nop-templates.com/t/licensinginfo
*/
#media all and (max-width: 1000px) {
#sevenspikes-cloud-zoom:before {
display: none;
}
#sevenspikes-cloud-zoom img {
position: static;
}
}
#media all and (min-width: 1001px) {
/* theme overwritting styles */
.gallery {
font-size: 0;
}
.gallery .picture-wrapper {
/*** !!! set line-height to the appropriate height !!! ***/
line-height: 320px;
}
.gallery .picture-wrapper .picture:before {
display: none;
}
/* main picture styles */
#sevenspikes-cloud-zoom {
margin: 0;
overflow: visible;
text-align: center;
font-size: 0;
}
#sevenspikes-cloud-zoom:before {
display: none;
}
#wrap {
display: block;
max-width: 100%;
vertical-align: middle;
line-height: 0;
}
#wrap a {
position: relative;
max-width: 100%;
vertical-align: middle;
line-height: 0;
overflow: hidden;
}
#wrap a:before {
content: "";
display: block;
padding-top: 125%;
}
#wrap img {
}
/* This is the overlay element. */
#wrap > .mousetrap {
right: 0;
bottom: 0;
margin: auto;
}
.cloud-zoom-lens {
margin: 0;
border: none;
background-color: #fff;
cursor: crosshair;
}
/* This is the zoom window. */
#cloudZoomWindowElement {
left: 0;
top: 0;
z-index: 1;
}
#cloud-zoom-big {
border: none;
overflow: hidden;
bottom: 0;
margin: auto;
}
.overview #cloud-zoom-big {
position: static !important; /* fix for the zoom window so that its wrapper takes the dimensions */
}
/* This is for the title text. */
.cloud-zoom-title {
background-color: #000;
padding: 5px;
text-align: center;
font-size: 11px;
line-height: normal;
font-weight: bold;
color: #fff;
}
/* This is the loading message. */
.cloud-zoom-loading {
width: 100% !important;
height: 100% !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
font-size: 0;
background: rgba(255,255,255,.5);
opacity: 1 !important;
}
#keyframes spinner {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.cloud-zoom-loading:after,
.cloud-zoom-loading:before {
content: '';
position: absolute;
border: 2px solid #454545;
width: 30px;
height: 30px;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
outline: 1px solid transparent; /*firefox fix*/
}
.cloud-zoom-loading:after {
animation: spinner 2.5s linear infinite;
}
.cloud-zoom-loading:before {
width: 44px;
height: 44px;
animation: spinner 2.5s linear infinite;
animation-direction: reverse;
}
/* with product ribbons enabled */
.gallery .ribbon-wrapper {
/*never display as inline or inline-block*/
vertical-align: middle;
line-height: 0;
}
.gallery .ribbon-wrapper:hover .ribbon-position {
opacity: 0;
}
}
CSHTML file
#** Copyright 2016 Seven Spikes Ltd. All rights reserved. (http://www.nop-templates.com)
* http://www.nop-templates.com/t/licensinginfo
*#
#using Nop.Core
#using Nop.Core.Infrastructure
#using SevenSpikes.Nop.Plugins.CloudZoom.Models
#model CloudZoomModel
#if (!string.IsNullOrEmpty(Model.DefaultPicture.FullSizeImageUrl))
{
Html.AddCssFileParts("~/Plugins/SevenSpikes.Nop.Plugins.CloudZoom/Themes/" + Model.Theme + "/Content/cloud-zoom.1.0.2/CloudZoom.css");
var supportRtl = EngineContext.Current.Resolve<IWorkContext>().WorkingLanguage.Rtl;
if (supportRtl)
{
Html.AddCssFileParts("~/Plugins/SevenSpikes.Nop.Plugins.CloudZoom/Styles/CloudZoom.common.rtl.css");
}
Html.AddScriptParts("~/Plugins/SevenSpikes.Core/Scripts/SevenSpikesExtensions.min.js");
Html.AddScriptParts("~/Plugins/SevenSpikes.Nop.Plugins.CloudZoom/Scripts/cloud-zoom.1.0.2/cloud-zoom.1.0.2.min.js");
if (Model.IsIntegratedByWidget)
{
Html.AddScriptParts("~/Plugins/SevenSpikes.Nop.Plugins.CloudZoom/Scripts/CloudZoom.min.js");
}
if (Model.EnableClickToZoom)
{
Html.AddCssFileParts("~/Content/magnific-popup/magnific-popup.css");
Html.AddScriptParts("~/Scripts/jquery.magnific-popup.min.js");
<script type="text/javascript">
$(document).ready(function () {
$(".picture").on("click", ".mousetrap", function () {
var mainPictureHref = $('.picture a.cloud-zoom').attr('href');
var cloudZoomThumbs = $('.picture-thumbs a.cloud-zoom-gallery');
var imgSources = new Array();
var imgItem = function(source) {
this.src = source;
};
cloudZoomThumbs.each(function(){
imgSources.push(new imgItem($(this).attr('href')));
});
if(imgSources.length === 0){
imgSources.push(new imgItem(mainPictureHref));
}
$.magnificPopup.open({
items: imgSources,
type: 'image',
removalDelay: 300,
gallery: {
enabled: true
}
}, cloudZoomThumbs.filter('.active').index());
});
});
</script>
}
<script type="text/javascript">
#{
string pictureAdjustmentTableName = string.Format("productAttributeValueAdjustmentTable_{0}", Model.ProductId);
string pictureAdjustmentFuncName = string.Format("adjustProductAttributeValuePicture_CloudZoom_{0}", Model.ProductId);
string pictureFullSizePrefix = "fullsize";
}
function #(pictureAdjustmentFuncName)(controlId) {
var ctrl = $('#' + controlId);
var pictureFullSizeUrl = '';
if((ctrl.is(':radio') && ctrl.is(':checked')) || (ctrl.is(':checkbox') && ctrl.is(':checked'))) {
pictureFullSizeUrl = #(pictureAdjustmentTableName)[controlId + '_#(pictureFullSizePrefix)'];
} else if(ctrl.is('select')) {
var idx = $('#' + controlId + " option").index($('#' + controlId + " option:selected"));
if(idx !== -1) {
pictureFullSizeUrl = #(pictureAdjustmentTableName)[controlId + '_#(pictureFullSizePrefix)'][idx];
}
}
if (typeof pictureFullSizeUrl == 'string' && pictureFullSizeUrl !== '') {
var zoomGallerySelector = ".cloud-zoom-gallery[href='" + pictureFullSizeUrl + "']";
$(zoomGallerySelector).click();
$.event.trigger({
type: 'nopMainProductImageChanged',
target: ctrl,
pictureDefaultSizeUrl: pictureFullSizeUrl,
pictureFullSizeUrl: pictureFullSizeUrl
});
}
}
$(document).ready(function () {
$("[id^='product_attribute_']").on('change', function() {
#(pictureAdjustmentFuncName)($(this).attr('id'));
});
});
</script>
<div class="gallery sevenspikes-cloudzoom-gallery">
<div class="picture-wrapper">
<div class="picture" id="sevenspikes-cloud-zoom" data-zoomwindowelementid="#Model.ElementId"
data-selectoroftheparentelementofthecloudzoomwindow="#Model.SettingsModel.SelectorOfTheParentElementOfTheCloudZoomWindow"
data-defaultimagecontainerselector="#Model.SettingsModel.DefaultImageContainerSelector">
<a href="#Model.DefaultPicture.FullSizeImageUrl" class="cloud-zoom" id="zoom1" rel="#Model.DefaultPicture.DefaultRelation">
<img src="#Model.DefaultPicture.SmallImageUrl" alt="#Model.DefaultPicture.AlternateText" title="#Model.DefaultPicture.Title" id="cloudZoomImage" itemprop="image" />
</a>
#if (Model.Pictures.Count > 1)
{
<div class="picture-thumbs-navigation-arrow picture-thumbs-prev-arrow">
<span>#T("SevenSpikes.Themes.Uptown.Product.ImageThumbs.Prev")</span>
<img src="#Model.DefaultPicture.TinyImageUrl" data-fullSizeImageUrl="#Model.DefaultPicture.FullSizeImageUrl" alt="Previous" />
</div>
<div class="picture-thumbs-navigation-arrow picture-thumbs-next-arrow">
<span>#T("SevenSpikes.Themes.Uptown.Product.ImageThumbs.Next")</span>
<img src="#Model.DefaultPicture.TinyImageUrl" data-fullSizeImageUrl="#Model.DefaultPicture.FullSizeImageUrl" alt="Next" />
</div>
<div class="picture-thumbs">
#foreach (var picture in Model.Pictures)
{
<a class="cloud-zoom-gallery" href="#picture.FullSizeImageUrl" title="#picture.Title" rel="#picture.GalleryRelation">
<img class="cloud-zoom-gallery-img" src="#picture.TinyImageUrl" alt="#picture.AlternateText" title="#picture.Title" />
</a>
}
</div>
}
</div>
</div>
</div>
}
Any ideas? More files needed to resolve this issue? LMK!
Please I need I help on how to implement something like this responsively using bootstrap
html code for is displayed below
<div class="wrapper">
<div class="container">
<div class="special">
<div id="counter">
<div id="shading"></div>
</div>
</div>
</div>
please below is the css file for the above html code
.special
{
position: relative;
width: 840px;
height: 247px;
background-image: url('https://www.jqueryscript.net/demo/Colorful-Countdown-Timer/images/special_offer_bg.png');
background-position: -10px 74px;
background-repeat: no-repeat;
}
#counter
{
position: absolute;
top: 135px;
left: 279px;
z-index: 4000;
}
.digit-separator
{
position: relative;
float: left;
width: 17px;
height: 44px;
overflow: hidden;
background-image: url('https://www.jqueryscript.net/demo/Colorful-Countdown-Timer/images/digit_separator.png');
background-repeat: no-repeat;
background-position: 0px 0px;
}
.digit
{
background-image: url('https://www.jqueryscript.net/demo/Colorful-Countdown-Timer/images/digits.png');
}
#shading
{
background-image: url('https://www.jqueryscript.net/demo/Colorful-Countdown-Timer/images/sprites.png');
background-position: 0px -396px;
background-repeat: repeat-x;
float: left;
height: 44px;
position: absolute;
width: 291px;
z-index: 4100;
top: 0;
left: 0;
}
please this is the JavaScript code for the above html code
function C3Counter(id, opt) {
this.options = {
stepTime: 60, // not used
format: "dd:hh:mm:ss", // not used
startTime: "01:04:40:59",
digitImages: 1,
digitWidth: 30,
digitHeight: 44,
digitSlide : true,
digitSlideTime : 200,
digitImageHeight : 484,
digitAnimationHeight : 44,
timerEnd: function(){},
image: "digits.png",
updateInterval : 1000
};
var s;
if (typeof opt != "undefined") {
for (s in this.options) {
if (typeof opt[s] != "undefined") {
this.options[s] = opt[s];
}
}
}
if (String(options.startTime).indexOf(":") == -1) {
options.tempStartTime = options.startTime;
} else {
//TODO - does not convert time with : to seconds to count
var td = new Date(options.startTime);
}
this.pad2 = function(number) {
return (number < 10 ? '0' : '') + number;
}
var timer = setInterval( "this.updateCounter()", options.updateInterval);
var startTime = new Date().getTime();
var secNo = 0;
var timerSingle = new Array();
var dc = 0;
var digits = new Array();
var d = new Date();
var lastTime = d.getTime();
this.calculateTime = function() {
var tempTime = options.tempStartTime;
if (String(options.tempStartTime).indexOf(":") == -1) {
var seconds=Math.round(options.tempStartTime % 60);
options.tempStartTime=Math.floor(options.tempStartTime/60);
var minutes=Math.round(options.tempStartTime % 60);
options.tempStartTime=Math.floor(options.tempStartTime/60);
var hours=Math.round(options.tempStartTime % 24);
options.tempStartTime=Math.floor(options.tempStartTime/24);
var days=Math.round(options.tempStartTime);
options.timeStr = this.pad2(days)+this.pad2(hours)+this.pad2(minutes)+this.pad2(seconds);
}
var currTime = new Date().getTime();
var diff = currTime - startTime;
options.tempStartTime = options.startTime - Math.round(diff/1000);
}
this.calculateTime();
for (dc=0; dc<8; dc++) {
digits[dc] = { digit: this.options.timeStr.charAt(dc)};
$("#"+id).append("<div id='digit"+dc+"' style='position:relative;float:left;width:"+this.options.digitWidth+"px;height:"+this.options.digitHeight+"px;overflow:hidden;'><div class='digit' id='digit-bg"+dc+"' style='position:absolute; top:-"+digits[dc].digit*this.options.digitAnimationHeight+"px; width:"+this.options.digitWidth+"px; height:"+this.options.digitImageHeight+"px; '></div></div>");
if (dc % 2 == 1 && dc < 6) {
$("#"+id).append("<div class='digit-separator' style='float:left;'></div>");
}
}
$("#"+id).append("<div style='clear:both'></div>");
this.animateDigits = function() {
for (var dc=0; dc<8; dc++) {
digits[dc].digitNext = Number(this.options.timeStr.charAt(dc));
digits[dc].digitNext = (digits[dc].digitNext + 10)%10;
var no = dc;
if (digits[no].digit == 0) $("#digit-bg"+no).css("top", -this.options.digitImageHeight+this.options.digitHeight + "px");
if (digits[no].digit != digits[no].digitNext) {
$("#digit-bg"+no).animate( { "top" : -digits[no].digitNext*options.digitHeight+"px"}, options.digitSlideTime);
digits[no].digit = digits[no].digitNext;
}
}
var end = this.checkEnd();
}
this.checkEnd = function() {
for (var i = 0; i < digits.length; i++) {
if (digits[i].digit != 0) {
return false;
}
}
clearInterval(timer);
this.options.timerEnd();
return true;
}
this.updateCounter = function() {
d = new Date();
if ((d.getTime() - lastTime) < (options.updateInterval - 50)) {
return;
}
lastTime = d.getTime();
this.calculateTime();
this.animateDigits();
}
}
C3Counter("counter", { startTime :16100 });
Note* you need to use Bootstrap v3.3.4 or higher and jQuery v2.1.3 or higher
Note* This doesnt look like the exact example you linked to. Its not posible to achieve that with default boostrap library.
html:
<div class="wrapper">
<div class="special">
<span id="clock"></span>
</div>
</div>
js:
$('#clock').countdown('2020/10/10', function(event) {
$(this).html(event.strftime('%D days %H:%M:%S'));
});
css:
.wrapper
{
width: 100%;
height: auto;
background-color: #dc403b;
}
.special
{
width:100%;
background-image: url('https://www.jqueryscript.net/demo/Colorful-Countdown-Timer/images/special_offer_bg.png');
background-position: cover;
background-repeat: no-repeat;
text-align: center;
padding: 50px 0;
font-size: 18px;
}