mirror of
https://github.com/9001/copyparty.git
synced 2025-08-19 09:52:21 -06:00
image viewer: add rotation
This commit is contained in:
parent
0bf41ed4ef
commit
41867f578f
|
@ -249,13 +249,14 @@ the browser has the following hotkeys (assumes qwerty, ignores actual layout)
|
||||||
* `J/L, Left/Right` prev/next file
|
* `J/L, Left/Right` prev/next file
|
||||||
* `Home/End` first/last file
|
* `Home/End` first/last file
|
||||||
* `S` toggle selection
|
* `S` toggle selection
|
||||||
|
* `R` rotate clockwise (shift=ccw)
|
||||||
* `Esc` close viewer
|
* `Esc` close viewer
|
||||||
* videos:
|
* videos:
|
||||||
* `U/O` skip 10sec back/forward
|
* `U/O` skip 10sec back/forward
|
||||||
* `P/K/Space` play/pause
|
* `P/K/Space` play/pause
|
||||||
* `F` fullscreen
|
* `F` fullscreen
|
||||||
* `C` continue playing next video
|
* `C` continue playing next video
|
||||||
* `R` loop
|
* `V` loop
|
||||||
* `M` mute
|
* `M` mute
|
||||||
* when the navpane is open:
|
* when the navpane is open:
|
||||||
* `A/D` adjust tree width
|
* `A/D` adjust tree width
|
||||||
|
|
|
@ -22,7 +22,7 @@ window.baguetteBox = (function () {
|
||||||
afterHide: null,
|
afterHide: null,
|
||||||
onChange: null,
|
onChange: null,
|
||||||
},
|
},
|
||||||
overlay, slider, btnPrev, btnNext, btnHelp, btnSel, btnVmode, btnClose,
|
overlay, slider, btnPrev, btnNext, btnHelp, btnRotL, btnRotR, btnSel, btnVmode, btnClose,
|
||||||
currentGallery = [],
|
currentGallery = [],
|
||||||
currentIndex = 0,
|
currentIndex = 0,
|
||||||
isOverlayVisible = false,
|
isOverlayVisible = false,
|
||||||
|
@ -175,6 +175,8 @@ window.baguetteBox = (function () {
|
||||||
'<button id="bbox-next" class="bbox-btn" type="button" aria-label="Next">></button>' +
|
'<button id="bbox-next" class="bbox-btn" type="button" aria-label="Next">></button>' +
|
||||||
'<div id="bbox-btns">' +
|
'<div id="bbox-btns">' +
|
||||||
'<button id="bbox-help" type="button">?</button>' +
|
'<button id="bbox-help" type="button">?</button>' +
|
||||||
|
'<button id="bbox-rotl" type="button">↶</button>' +
|
||||||
|
'<button id="bbox-rotr" type="button">↷</button>' +
|
||||||
'<button id="bbox-tsel" type="button">sel</button>' +
|
'<button id="bbox-tsel" type="button">sel</button>' +
|
||||||
'<button id="bbox-vmode" type="button" tt="a"></button>' +
|
'<button id="bbox-vmode" type="button" tt="a"></button>' +
|
||||||
'<button id="bbox-close" type="button" aria-label="Close">X</button>' +
|
'<button id="bbox-close" type="button" aria-label="Close">X</button>' +
|
||||||
|
@ -188,6 +190,8 @@ window.baguetteBox = (function () {
|
||||||
btnPrev = ebi('bbox-prev');
|
btnPrev = ebi('bbox-prev');
|
||||||
btnNext = ebi('bbox-next');
|
btnNext = ebi('bbox-next');
|
||||||
btnHelp = ebi('bbox-help');
|
btnHelp = ebi('bbox-help');
|
||||||
|
btnRotL = ebi('bbox-rotl');
|
||||||
|
btnRotR = ebi('bbox-rotr');
|
||||||
btnSel = ebi('bbox-tsel');
|
btnSel = ebi('bbox-tsel');
|
||||||
btnVmode = ebi('bbox-vmode');
|
btnVmode = ebi('bbox-vmode');
|
||||||
btnClose = ebi('bbox-close');
|
btnClose = ebi('bbox-close');
|
||||||
|
@ -205,12 +209,13 @@ window.baguetteBox = (function () {
|
||||||
['right, L', 'next file'],
|
['right, L', 'next file'],
|
||||||
['home', 'first file'],
|
['home', 'first file'],
|
||||||
['end', 'last file'],
|
['end', 'last file'],
|
||||||
|
['R', 'rotate (shift=ccw)'],
|
||||||
['S', 'toggle file selection'],
|
['S', 'toggle file selection'],
|
||||||
['space, P, K', 'video: play / pause'],
|
['space, P, K', 'video: play / pause'],
|
||||||
['U', 'video: seek 10sec back'],
|
['U', 'video: seek 10sec back'],
|
||||||
['P', 'video: seek 10sec ahead'],
|
['P', 'video: seek 10sec ahead'],
|
||||||
['M', 'video: toggle mute'],
|
['M', 'video: toggle mute'],
|
||||||
['R', 'video: toggle loop'],
|
['V', 'video: toggle loop'],
|
||||||
['C', 'video: toggle auto-next'],
|
['C', 'video: toggle auto-next'],
|
||||||
['F', 'video: toggle fullscreen'],
|
['F', 'video: toggle fullscreen'],
|
||||||
],
|
],
|
||||||
|
@ -252,7 +257,7 @@ window.baguetteBox = (function () {
|
||||||
v.muted = vmute = !vmute;
|
v.muted = vmute = !vmute;
|
||||||
mp_ctl();
|
mp_ctl();
|
||||||
}
|
}
|
||||||
else if (k == "KeyR" && v) {
|
else if (k == "KeyV" && v) {
|
||||||
vloop = !vloop;
|
vloop = !vloop;
|
||||||
vnext = vnext && !vloop;
|
vnext = vnext && !vloop;
|
||||||
setVmode();
|
setVmode();
|
||||||
|
@ -272,6 +277,8 @@ window.baguetteBox = (function () {
|
||||||
catch (ex) { }
|
catch (ex) { }
|
||||||
else if (k == "KeyS")
|
else if (k == "KeyS")
|
||||||
tglsel();
|
tglsel();
|
||||||
|
else if (k == "KeyR")
|
||||||
|
rotn(e.shiftKey ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVmode() {
|
function setVmode() {
|
||||||
|
@ -284,7 +291,7 @@ window.baguetteBox = (function () {
|
||||||
if (vloop) {
|
if (vloop) {
|
||||||
lbl = 'Loop';
|
lbl = 'Loop';
|
||||||
msg += 'repeat it';
|
msg += 'repeat it';
|
||||||
tts = '$NHotkey: R';
|
tts = '$NHotkey: V';
|
||||||
}
|
}
|
||||||
else if (vnext) {
|
else if (vnext) {
|
||||||
lbl = 'Cont';
|
lbl = 'Cont';
|
||||||
|
@ -333,7 +340,7 @@ window.baguetteBox = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function selbg() {
|
function selbg() {
|
||||||
var img = imagesElements[currentIndex].querySelector('img, video'),
|
var img = vidimg(),
|
||||||
thumb = currentGallery[currentIndex].imageElement,
|
thumb = currentGallery[currentIndex].imageElement,
|
||||||
name = vsplit(thumb.href)[1],
|
name = vsplit(thumb.href)[1],
|
||||||
files = msel.getsel(),
|
files = msel.getsel(),
|
||||||
|
@ -387,6 +394,8 @@ window.baguetteBox = (function () {
|
||||||
bind(btnClose, 'click', hideOverlay);
|
bind(btnClose, 'click', hideOverlay);
|
||||||
bind(btnVmode, 'click', tglVmode);
|
bind(btnVmode, 'click', tglVmode);
|
||||||
bind(btnHelp, 'click', halp);
|
bind(btnHelp, 'click', halp);
|
||||||
|
bind(btnRotL, 'click', rotl);
|
||||||
|
bind(btnRotR, 'click', rotr);
|
||||||
bind(btnSel, 'click', tglsel);
|
bind(btnSel, 'click', tglsel);
|
||||||
bind(slider, 'contextmenu', contextmenuHandler);
|
bind(slider, 'contextmenu', contextmenuHandler);
|
||||||
bind(overlay, 'touchstart', touchstartHandler, nonPassiveEvent);
|
bind(overlay, 'touchstart', touchstartHandler, nonPassiveEvent);
|
||||||
|
@ -402,6 +411,8 @@ window.baguetteBox = (function () {
|
||||||
unbind(btnClose, 'click', hideOverlay);
|
unbind(btnClose, 'click', hideOverlay);
|
||||||
unbind(btnVmode, 'click', tglVmode);
|
unbind(btnVmode, 'click', tglVmode);
|
||||||
unbind(btnHelp, 'click', halp);
|
unbind(btnHelp, 'click', halp);
|
||||||
|
unbind(btnRotL, 'click', rotl);
|
||||||
|
unbind(btnRotR, 'click', rotr);
|
||||||
unbind(btnSel, 'click', tglsel);
|
unbind(btnSel, 'click', tglsel);
|
||||||
unbind(slider, 'contextmenu', contextmenuHandler);
|
unbind(slider, 'contextmenu', contextmenuHandler);
|
||||||
unbind(overlay, 'touchstart', touchstartHandler, nonPassiveEvent);
|
unbind(overlay, 'touchstart', touchstartHandler, nonPassiveEvent);
|
||||||
|
@ -658,10 +669,56 @@ window.baguetteBox = (function () {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rotn(n) {
|
||||||
|
var el = vidimg(),
|
||||||
|
orot = parseInt(el.getAttribute('rot') || 0),
|
||||||
|
frot = orot + n * 90,
|
||||||
|
rot = frot,
|
||||||
|
iw = el.naturalWidth || el.videoWidth,
|
||||||
|
ih = el.naturalHeight || el.videoHeight,
|
||||||
|
magic = 4, // idk, works in enough browsers
|
||||||
|
co = ebi('bbox-overlay'),
|
||||||
|
dl = el.closest('div').querySelector('figcaption a'),
|
||||||
|
vw = co.clientWidth,
|
||||||
|
vh = co.clientHeight - dl.offsetHeight + magic,
|
||||||
|
pmag = Math.min(1, Math.min(vw / ih, vh / iw)),
|
||||||
|
wmag = Math.min(1, Math.min(vw / iw, vh / ih));
|
||||||
|
|
||||||
|
while (rot < 0) rot += 360;
|
||||||
|
while (rot >= 360) rot -= 360;
|
||||||
|
var q = rot == 90 || rot == 270 ? 1 : 0,
|
||||||
|
mag = q ? pmag : wmag;
|
||||||
|
|
||||||
|
el.style.cssText = 'max-width:none; max-height:none; position:absolute; display:block; margin:0';
|
||||||
|
if (!orot) {
|
||||||
|
el.style.width = iw * wmag + 'px';
|
||||||
|
el.style.height = ih * wmag + 'px';
|
||||||
|
el.style.left = (vw - iw * wmag) / 2 + 'px';
|
||||||
|
el.style.top = (vh - ih * wmag) / 2 - magic + 'px';
|
||||||
|
q = el.offsetHeight;
|
||||||
|
}
|
||||||
|
el.style.width = iw * mag + 'px';
|
||||||
|
el.style.height = ih * mag + 'px';
|
||||||
|
el.style.left = (vw - iw * mag) / 2 + 'px';
|
||||||
|
el.style.top = (vh - ih * mag) / 2 - magic + 'px';
|
||||||
|
el.style.transform = 'rotate(' + frot + 'deg)';
|
||||||
|
el.setAttribute('rot', frot);
|
||||||
|
}
|
||||||
|
function rotl() {
|
||||||
|
rotn(-1);
|
||||||
|
}
|
||||||
|
function rotr() {
|
||||||
|
rotn(1);
|
||||||
|
}
|
||||||
|
|
||||||
function vid() {
|
function vid() {
|
||||||
return imagesElements[currentIndex].querySelector('video');
|
return imagesElements[currentIndex].querySelector('video');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function vidimg() {
|
||||||
|
return imagesElements[currentIndex].querySelector('img, video');
|
||||||
|
}
|
||||||
|
|
||||||
function playvid(play) {
|
function playvid(play) {
|
||||||
if (vid())
|
if (vid())
|
||||||
vid()[play ? 'play' : 'pause']();
|
vid()[play ? 'play' : 'pause']();
|
||||||
|
|
|
@ -1329,6 +1329,7 @@ html.light #tree::-webkit-scrollbar {
|
||||||
margin-bottom: 1.4em;
|
margin-bottom: 1.4em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||||
|
transition: transform .2s, left .2s, top .2s, width .2s, height .2s;
|
||||||
}
|
}
|
||||||
.full-image video {
|
.full-image video {
|
||||||
background: #333;
|
background: #333;
|
||||||
|
@ -1341,6 +1342,7 @@ html.light #tree::-webkit-scrollbar {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
#bbox-overlay figcaption a {
|
#bbox-overlay figcaption a {
|
||||||
background: rgba(0, 0, 0, 0.6);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
|
Loading…
Reference in a new issue