Media viewer: added zooming
This commit is contained in:
parent
1b4c51345c
commit
ab6a7e1725
@ -51,6 +51,13 @@ import setInnerHTML from "../helpers/dom/setInnerHTML";
|
|||||||
import { doubleRaf, fastRaf } from "../helpers/schedulers";
|
import { doubleRaf, fastRaf } from "../helpers/schedulers";
|
||||||
import { attachClickEvent } from "../helpers/dom/clickEvent";
|
import { attachClickEvent } from "../helpers/dom/clickEvent";
|
||||||
import PopupDeleteMessages from "./popups/deleteMessages";
|
import PopupDeleteMessages from "./popups/deleteMessages";
|
||||||
|
import RangeSelector from "./rangeSelector";
|
||||||
|
import attachGrabListeners, { GrabEvent } from "../helpers/dom/attachGrabListeners";
|
||||||
|
|
||||||
|
const ZOOM_STEP = 0.5;
|
||||||
|
const ZOOM_INITIAL_VALUE = 1;
|
||||||
|
const ZOOM_MIN_VALUE = 1;
|
||||||
|
const ZOOM_MAX_VALUE = 4;
|
||||||
|
|
||||||
// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию
|
// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию
|
||||||
// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)
|
// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)
|
||||||
@ -63,8 +70,9 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
protected overlaysDiv: HTMLElement;
|
protected overlaysDiv: HTMLElement;
|
||||||
protected author: {[k in 'container' | 'avatarEl' | 'nameEl' | 'date']: HTMLElement} = {} as any;
|
protected author: {[k in 'container' | 'avatarEl' | 'nameEl' | 'date']: HTMLElement} = {} as any;
|
||||||
protected content: {[k in 'main' | 'container' | 'media' | 'mover' | ContentAdditionType]: HTMLElement} = {} as any;
|
protected content: {[k in 'main' | 'container' | 'media' | 'mover' | ContentAdditionType]: HTMLElement} = {} as any;
|
||||||
protected buttons: {[k in 'download' | 'close' | 'prev' | 'next' | 'mobile-close' | 'zoomin' | ButtonsAdditionType]: HTMLElement} = {} as any;
|
protected buttons: {[k in 'download' | 'close' | 'prev' | 'next' | 'mobile-close' | 'zoom' | ButtonsAdditionType]: HTMLElement} = {} as any;
|
||||||
protected topbar: HTMLElement;
|
protected topbar: HTMLElement;
|
||||||
|
protected moversContainer: HTMLElement;
|
||||||
|
|
||||||
protected tempId = 0;
|
protected tempId = 0;
|
||||||
protected preloader: ProgressivePreloader = null;
|
protected preloader: ProgressivePreloader = null;
|
||||||
@ -102,7 +110,22 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
protected loadMoreMedia: (older: boolean) => Promise<void>;
|
protected loadMoreMedia: (older: boolean) => Promise<void>;
|
||||||
|
|
||||||
protected videoPlayer: VideoPlayer;
|
protected videoPlayer: VideoPlayer;
|
||||||
|
|
||||||
|
protected zoomElements: {
|
||||||
|
container: HTMLElement,
|
||||||
|
btnOut: HTMLElement,
|
||||||
|
btnIn: HTMLElement,
|
||||||
|
rangeSelector: RangeSelector
|
||||||
|
} = {} as any;
|
||||||
|
// protected zoomValue = ZOOM_INITIAL_VALUE;
|
||||||
|
protected zoomSwipeHandler: SwipeHandler;
|
||||||
|
protected zoomSwipeStartX = 0;
|
||||||
|
protected zoomSwipeStartY = 0;
|
||||||
|
protected zoomSwipeX = 0;
|
||||||
|
protected zoomSwipeY = 0;
|
||||||
|
|
||||||
|
protected ctrlKeyDown: boolean;
|
||||||
|
|
||||||
constructor(topButtons: Array<keyof AppMediaViewerBase<ContentAdditionType, ButtonsAdditionType, TargetType>['buttons']>) {
|
constructor(topButtons: Array<keyof AppMediaViewerBase<ContentAdditionType, ButtonsAdditionType, TargetType>['buttons']>) {
|
||||||
this.log = logger('AMV');
|
this.log = logger('AMV');
|
||||||
this.preloader = new ProgressivePreloader();
|
this.preloader = new ProgressivePreloader();
|
||||||
@ -153,12 +176,34 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
const buttonsDiv = document.createElement('div');
|
const buttonsDiv = document.createElement('div');
|
||||||
buttonsDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-buttons');
|
buttonsDiv.classList.add(MEDIA_VIEWER_CLASSNAME + '-buttons');
|
||||||
|
|
||||||
topButtons.concat(['download', 'zoomin', 'close']).forEach(name => {
|
topButtons.concat(['download', 'zoom', 'close']).forEach(name => {
|
||||||
const button = ButtonIcon(name, {noRipple: name === 'close' || undefined});
|
const button = ButtonIcon(name, {noRipple: true});
|
||||||
this.buttons[name] = button;
|
this.buttons[name] = button;
|
||||||
buttonsDiv.append(button);
|
buttonsDiv.append(button);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.buttons.zoom.classList.add('zoom-in');
|
||||||
|
|
||||||
|
// * zoom
|
||||||
|
this.zoomElements.container = document.createElement('div');
|
||||||
|
this.zoomElements.container.classList.add('zoom-container');
|
||||||
|
|
||||||
|
this.zoomElements.btnOut = ButtonIcon('zoomout', {noRipple: true});
|
||||||
|
this.zoomElements.btnOut.addEventListener('click', () => this.changeZoom(false));
|
||||||
|
this.zoomElements.btnIn = ButtonIcon('zoomin', {noRipple: true});
|
||||||
|
this.zoomElements.btnIn.addEventListener('click', () => this.changeZoom(true));
|
||||||
|
|
||||||
|
this.zoomElements.rangeSelector = new RangeSelector(ZOOM_STEP, ZOOM_INITIAL_VALUE + ZOOM_STEP, ZOOM_MIN_VALUE, ZOOM_MAX_VALUE, true);
|
||||||
|
this.zoomElements.rangeSelector.setListeners();
|
||||||
|
this.zoomElements.rangeSelector.setHandlers({
|
||||||
|
onScrub: this.setZoomValue,
|
||||||
|
onMouseUp: () => this.setZoomValue()
|
||||||
|
});
|
||||||
|
|
||||||
|
this.zoomElements.container.append(this.zoomElements.btnOut, this.zoomElements.rangeSelector.container, this.zoomElements.btnIn);
|
||||||
|
|
||||||
|
this.wholeDiv.append(this.zoomElements.container);
|
||||||
|
|
||||||
// * content
|
// * content
|
||||||
this.content.main = document.createElement('div');
|
this.content.main = document.createElement('div');
|
||||||
this.content.main.classList.add(MEDIA_VIEWER_CLASSNAME + '-content');
|
this.content.main.classList.add(MEDIA_VIEWER_CLASSNAME + '-content');
|
||||||
@ -187,7 +232,17 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
this.buttons.next.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-right`;
|
this.buttons.next.className = `${MEDIA_VIEWER_CLASSNAME}-switcher ${MEDIA_VIEWER_CLASSNAME}-switcher-right`;
|
||||||
this.buttons.next.innerHTML = `<span class="tgico-down ${MEDIA_VIEWER_CLASSNAME}-next-button"></span>`;
|
this.buttons.next.innerHTML = `<span class="tgico-down ${MEDIA_VIEWER_CLASSNAME}-next-button"></span>`;
|
||||||
|
|
||||||
this.wholeDiv.append(this.overlaysDiv, this.buttons.prev, this.buttons.next, this.topbar);
|
this.moversContainer = document.createElement('div');
|
||||||
|
this.moversContainer.classList.add(MEDIA_VIEWER_CLASSNAME + '-movers');
|
||||||
|
this.moversContainer.addEventListener('wheel', (e) => {
|
||||||
|
if(this.ctrlKeyDown) {
|
||||||
|
cancelEvent(e);
|
||||||
|
const scrollingUp = e.deltaY < 0;
|
||||||
|
this.changeZoom(!!scrollingUp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.wholeDiv.append(this.overlaysDiv, this.buttons.prev, this.buttons.next, this.topbar, this.moversContainer);
|
||||||
|
|
||||||
// * constructing html end
|
// * constructing html end
|
||||||
|
|
||||||
@ -224,6 +279,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.buttons.zoom.addEventListener('click', () => this.toggleZoom());
|
||||||
|
|
||||||
this.wholeDiv.addEventListener('click', this.onClick);
|
this.wholeDiv.addEventListener('click', this.onClick);
|
||||||
|
|
||||||
if(isTouchSupported) {
|
if(isTouchSupported) {
|
||||||
@ -268,6 +325,80 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected toggleZoom(enable?: boolean) {
|
||||||
|
const isVisible = this.isZooming();
|
||||||
|
if(this.zoomElements.rangeSelector.mousedown || this.ctrlKeyDown) {
|
||||||
|
enable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isVisible === enable) return;
|
||||||
|
|
||||||
|
if(enable === undefined) {
|
||||||
|
enable = !isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.buttons.zoom.classList.toggle('zoom-in', !enable);
|
||||||
|
this.zoomElements.container.classList.toggle('is-visible', enable);
|
||||||
|
const zoomValue = enable ? ZOOM_INITIAL_VALUE + ZOOM_STEP : 1;
|
||||||
|
this.setZoomValue(zoomValue);
|
||||||
|
|
||||||
|
if(enable) {
|
||||||
|
if(!this.zoomSwipeHandler) {
|
||||||
|
let lastDiffX: number, lastDiffY: number;
|
||||||
|
const multiplier = -1;
|
||||||
|
this.zoomSwipeHandler = new SwipeHandler({
|
||||||
|
element: this.moversContainer,
|
||||||
|
onFirstSwipe: () => {
|
||||||
|
lastDiffX = lastDiffY = 0;
|
||||||
|
this.moversContainer.classList.add('no-transition');
|
||||||
|
},
|
||||||
|
onSwipe: (xDiff, yDiff) => {
|
||||||
|
[xDiff, yDiff] = [xDiff * multiplier, yDiff * multiplier];
|
||||||
|
this.zoomSwipeX += xDiff - lastDiffX;
|
||||||
|
this.zoomSwipeY += yDiff - lastDiffY;
|
||||||
|
[lastDiffX, lastDiffY] = [xDiff, yDiff];
|
||||||
|
|
||||||
|
this.setZoomValue();
|
||||||
|
},
|
||||||
|
onReset: () => {
|
||||||
|
this.moversContainer.classList.remove('no-transition');
|
||||||
|
},
|
||||||
|
cursor: 'move'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.zoomSwipeHandler.setListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.zoomElements.rangeSelector.setProgress(zoomValue);
|
||||||
|
} else if(!enable) {
|
||||||
|
this.zoomSwipeHandler.removeListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected changeZoom(add: boolean) {
|
||||||
|
this.zoomElements.rangeSelector.addProgress(ZOOM_STEP * (add ? 1 : -1));
|
||||||
|
this.setZoomValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected setZoomValue = (value = this.zoomElements.rangeSelector.value) => {
|
||||||
|
// this.zoomValue = value;
|
||||||
|
if(value === ZOOM_INITIAL_VALUE) {
|
||||||
|
this.zoomSwipeX = 0;
|
||||||
|
this.zoomSwipeY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.moversContainer.style.transform = `matrix(${value}, 0, 0, ${value}, ${this.zoomSwipeX}, ${this.zoomSwipeY})`;
|
||||||
|
|
||||||
|
this.zoomElements.btnOut.classList.toggle('inactive', value === ZOOM_MIN_VALUE);
|
||||||
|
this.zoomElements.btnIn.classList.toggle('inactive', value === ZOOM_MAX_VALUE);
|
||||||
|
|
||||||
|
this.toggleZoom(value > ZOOM_INITIAL_VALUE);
|
||||||
|
};
|
||||||
|
|
||||||
|
protected isZooming() {
|
||||||
|
return this.zoomElements.container.classList.contains('is-visible');
|
||||||
|
}
|
||||||
|
|
||||||
protected setBtnMenuToggle(buttons: ButtonMenuItemOptions[]) {
|
protected setBtnMenuToggle(buttons: ButtonMenuItemOptions[]) {
|
||||||
const btnMenuToggle = ButtonMenuToggle({onlyMobile: true}, 'bottom-left', buttons);
|
const btnMenuToggle = ButtonMenuToggle({onlyMobile: true}, 'bottom-left', buttons);
|
||||||
this.topbar.append(btnMenuToggle);
|
this.topbar.append(btnMenuToggle);
|
||||||
@ -294,6 +425,11 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
this.setMoverPromise = null;
|
this.setMoverPromise = null;
|
||||||
this.tempId = -1;
|
this.tempId = -1;
|
||||||
|
|
||||||
|
if(this.zoomSwipeHandler) {
|
||||||
|
this.zoomSwipeHandler.removeListeners();
|
||||||
|
this.zoomSwipeHandler = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) {
|
/* if(appSidebarRight.historyTabIDs.slice(-1)[0] === AppSidebarRight.SLIDERITEMSIDS.forward) {
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
appSidebarRight.forwardTab.closeBtn.click();
|
appSidebarRight.forwardTab.closeBtn.click();
|
||||||
@ -301,6 +437,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
window.removeEventListener('keydown', this.onKeyDown);
|
window.removeEventListener('keydown', this.onKeyDown);
|
||||||
|
window.removeEventListener('keyup', this.onKeyUp);
|
||||||
|
|
||||||
promise.finally(() => {
|
promise.finally(() => {
|
||||||
this.wholeDiv.remove();
|
this.wholeDiv.remove();
|
||||||
@ -333,26 +470,56 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isZooming = this.isZooming();
|
||||||
let mover: HTMLElement = null;
|
let mover: HTMLElement = null;
|
||||||
['media-viewer-mover', 'media-viewer-buttons', 'media-viewer-author', 'media-viewer-caption'].find(s => {
|
const classNames = ['ckin__player', 'media-viewer-buttons', 'media-viewer-author', 'media-viewer-caption', 'zoom-container'];
|
||||||
|
if(isZooming) {
|
||||||
|
classNames.push('media-viewer-movers');
|
||||||
|
}
|
||||||
|
|
||||||
|
classNames.find(s => {
|
||||||
try {
|
try {
|
||||||
mover = findUpClassName(target, s);
|
mover = findUpClassName(target, s);
|
||||||
if(mover) return true;
|
if(mover) return true;
|
||||||
} catch(err) {return false;}
|
} catch(err) {return false;}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(/* target === this.mediaViewerDiv */!mover || target.tagName === 'IMG' || target.tagName === 'image') {
|
if(/* target === this.mediaViewerDiv */!mover || (!isZooming && (target.tagName === 'IMG' || target.tagName === 'image'))) {
|
||||||
this.buttons.close.click();
|
this.buttons.close.click();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private onKeyDown = (e: KeyboardEvent) => {
|
private onKeyDown = (e: KeyboardEvent) => {
|
||||||
//this.log('onKeyDown', e);
|
//this.log('onKeyDown', e);
|
||||||
|
if(rootScope.overlaysActive > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let good = true;
|
||||||
if(e.key === 'ArrowRight') {
|
if(e.key === 'ArrowRight') {
|
||||||
this.buttons.next.click();
|
this.buttons.next.click();
|
||||||
} else if(e.key === 'ArrowLeft') {
|
} else if(e.key === 'ArrowLeft') {
|
||||||
this.buttons.prev.click();
|
this.buttons.prev.click();
|
||||||
|
} else {
|
||||||
|
good = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.ctrlKey || e.metaKey) {
|
||||||
|
this.ctrlKeyDown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(good) {
|
||||||
|
cancelEvent(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private onKeyUp = (e: KeyboardEvent) => {
|
||||||
|
if(!(e.ctrlKey || e.metaKey)) {
|
||||||
|
this.ctrlKeyDown = false;
|
||||||
|
|
||||||
|
if(this.isZooming()) {
|
||||||
|
this.setZoomValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,7 +537,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
//mover.append(this.buttons.prev, this.buttons.next);
|
//mover.append(this.buttons.prev, this.buttons.next);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeCenterFromMover(mover);
|
const zoomValue = this.isZooming() && closing /* && false */ ? this.zoomElements.rangeSelector.value : ZOOM_INITIAL_VALUE;
|
||||||
|
/* if(!(zoomValue > 1 && closing)) */ this.removeCenterFromMover(mover);
|
||||||
|
|
||||||
const wasActive = fromRight !== 0;
|
const wasActive = fromRight !== 0;
|
||||||
|
|
||||||
@ -444,6 +612,14 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
top = rect.top;
|
top = rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(zoomValue > 1) { // 33
|
||||||
|
// const diffX = (rect.width * zoomValue - rect.width) / 4;
|
||||||
|
const diffX = (rect.width * zoomValue - rect.width) / 2;
|
||||||
|
const diffY = (rect.height * zoomValue - rect.height) / 4;
|
||||||
|
// left -= diffX;
|
||||||
|
// top += diffY;
|
||||||
|
}
|
||||||
|
|
||||||
transform += `translate3d(${left}px,${top}px,0) `;
|
transform += `translate3d(${left}px,${top}px,0) `;
|
||||||
|
|
||||||
/* if(wasActive) {
|
/* if(wasActive) {
|
||||||
@ -485,6 +661,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
mover.style.width = containerRect.width + 'px';
|
mover.style.width = containerRect.width + 'px';
|
||||||
mover.style.height = containerRect.height + 'px';
|
mover.style.height = containerRect.height + 'px';
|
||||||
|
|
||||||
|
// const scaleX = rect.width / (containerRect.width * zoomValue);
|
||||||
|
// const scaleY = rect.height / (containerRect.height * zoomValue);
|
||||||
const scaleX = rect.width / containerRect.width;
|
const scaleX = rect.width / containerRect.width;
|
||||||
const scaleY = rect.height / containerRect.height;
|
const scaleY = rect.height / containerRect.height;
|
||||||
if(!wasActive) {
|
if(!wasActive) {
|
||||||
@ -499,7 +677,17 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
}
|
}
|
||||||
//let borderRadius = '0px 0px 0px 0px';
|
//let borderRadius = '0px 0px 0px 0px';
|
||||||
|
|
||||||
mover.style.transform = transform;
|
if(closing && zoomValue > 1) {
|
||||||
|
const width = this.moversContainer.scrollWidth * scaleX;
|
||||||
|
const height = this.moversContainer.scrollHeight * scaleY;
|
||||||
|
const willBeLeft = appPhotosManager.windowW / 2 - rect.width / 2;
|
||||||
|
const willBeTop = appPhotosManager.windowH / 2 - rect.height / 2;
|
||||||
|
const left = rect.left - willBeLeft/* + (width - rect.width) / 2 */;
|
||||||
|
const top = rect.top - willBeTop/* + (height - rect.height) / 2 */;
|
||||||
|
this.moversContainer.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${left}, ${top})`;
|
||||||
|
} else {
|
||||||
|
mover.style.transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
needOpacity && (mover.style.opacity = '0'/* !closing ? '0' : '' */);
|
needOpacity && (mover.style.opacity = '0'/* !closing ? '0' : '' */);
|
||||||
|
|
||||||
@ -663,6 +851,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
this.wholeDiv.classList.remove('active');
|
this.wholeDiv.classList.remove('active');
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
mover.style.borderRadius = borderRadius;
|
mover.style.borderRadius = borderRadius;
|
||||||
|
|
||||||
@ -679,10 +869,12 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}, delay);
|
}, delay);
|
||||||
|
|
||||||
|
mover.classList.remove('opening');
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
mover.classList.toggle('opening', !closing);
|
mover.classList.add('opening');
|
||||||
|
|
||||||
//await new Promise((resolve) => setTimeout(resolve, 0));
|
//await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
//await new Promise((resolve) => window.requestAnimationFrame(resolve));
|
//await new Promise((resolve) => window.requestAnimationFrame(resolve));
|
||||||
@ -713,7 +905,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
}, 0/* delay / 2 */);
|
}, 0/* delay / 2 */);
|
||||||
|
|
||||||
mover.dataset.timeout = '' + setTimeout(() => {
|
mover.dataset.timeout = '' + setTimeout(() => {
|
||||||
mover.classList.remove('moving');
|
mover.classList.remove('moving', 'opening');
|
||||||
|
|
||||||
if(aspecter) { // всё из-за видео, элементы управления скейлятся, так бы можно было этого не делать
|
if(aspecter) { // всё из-за видео, элементы управления скейлятся, так бы можно было этого не делать
|
||||||
if(mover.querySelector('video') || true) {
|
if(mover.querySelector('video') || true) {
|
||||||
@ -848,7 +1040,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
const oldMover = this.content.mover;
|
const oldMover = this.content.mover;
|
||||||
oldMover.parentElement.append(newMover);
|
oldMover.parentElement.append(newMover);
|
||||||
} else {
|
} else {
|
||||||
this.wholeDiv.append(newMover);
|
this.moversContainer.append(newMover);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.content.mover = newMover;
|
return this.content.mover = newMover;
|
||||||
@ -1014,6 +1206,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
this.setNewMover();
|
this.setNewMover();
|
||||||
} else {
|
} else {
|
||||||
window.addEventListener('keydown', this.onKeyDown);
|
window.addEventListener('keydown', this.onKeyDown);
|
||||||
|
window.addEventListener('keyup', this.onKeyUp);
|
||||||
const mainColumns = this.pageEl.querySelector('#main-columns');
|
const mainColumns = this.pageEl.querySelector('#main-columns');
|
||||||
this.pageEl.insertBefore(this.wholeDiv, mainColumns);
|
this.pageEl.insertBefore(this.wholeDiv, mainColumns);
|
||||||
void this.wholeDiv.offsetLeft; // reflow
|
void this.wholeDiv.offsetLeft; // reflow
|
||||||
@ -1039,13 +1232,13 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
|
|||||||
|
|
||||||
const mover = this.content.mover;
|
const mover = this.content.mover;
|
||||||
|
|
||||||
//const maxWidth = appPhotosManager.windowW - 16;
|
const maxWidth = appPhotosManager.windowW;
|
||||||
const maxWidth = this.pageEl.scrollWidth;
|
//const maxWidth = this.pageEl.scrollWidth;
|
||||||
// TODO: const maxHeight = mediaSizes.isMobile ? appPhotosManager.windowH : appPhotosManager.windowH - 100;
|
// TODO: const maxHeight = mediaSizes.isMobile ? appPhotosManager.windowH : appPhotosManager.windowH - 100;
|
||||||
let padding = 0;
|
let padding = 0;
|
||||||
const windowH = appPhotosManager.windowH;
|
const windowH = appPhotosManager.windowH;
|
||||||
if(windowH < 1000000 && !mediaSizes.isMobile) {
|
if(windowH < 1000000 && !mediaSizes.isMobile) {
|
||||||
padding = 32 + 120;
|
padding = 120;
|
||||||
}
|
}
|
||||||
const maxHeight = windowH - 120 - padding;
|
const maxHeight = windowH - 120 - padding;
|
||||||
let thumbPromise: Promise<any> = Promise.resolve();
|
let thumbPromise: Promise<any> = Promise.resolve();
|
||||||
|
@ -25,9 +25,12 @@ export default class RangeSelector {
|
|||||||
|
|
||||||
protected decimals: number;
|
protected decimals: number;
|
||||||
|
|
||||||
constructor(protected step: number, protected value: number, protected min: number, protected max: number) {
|
constructor(protected step: number, value: number, protected min: number, protected max: number, withTransition = false) {
|
||||||
this.container = document.createElement('div');
|
this.container = document.createElement('div');
|
||||||
this.container.classList.add('progress-line');
|
this.container.classList.add('progress-line');
|
||||||
|
if(withTransition) {
|
||||||
|
this.container.classList.add('with-transition');
|
||||||
|
}
|
||||||
|
|
||||||
this.filled = document.createElement('div');
|
this.filled = document.createElement('div');
|
||||||
this.filled.classList.add('progress-line__filled');
|
this.filled.classList.add('progress-line__filled');
|
||||||
@ -54,6 +57,10 @@ export default class RangeSelector {
|
|||||||
this.container.append(this.filled, seek);
|
this.container.append(this.filled, seek);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return +this.seek.value;
|
||||||
|
}
|
||||||
|
|
||||||
public setHandlers(events: RangeSelector['events']) {
|
public setHandlers(events: RangeSelector['events']) {
|
||||||
this.events = events;
|
this.events = events;
|
||||||
}
|
}
|
||||||
@ -86,8 +93,13 @@ export default class RangeSelector {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public setProgress(value: number) {
|
public setProgress(value: number) {
|
||||||
this.setFilled(value);
|
|
||||||
this.seek.value = '' + value;
|
this.seek.value = '' + value;
|
||||||
|
this.setFilled(+this.seek.value); // clamp
|
||||||
|
}
|
||||||
|
|
||||||
|
public addProgress(value: number) {
|
||||||
|
this.seek.value = '' + (+this.seek.value + value);
|
||||||
|
this.setFilled(+this.seek.value); // clamp
|
||||||
}
|
}
|
||||||
|
|
||||||
public setFilled(value: number) {
|
public setFilled(value: number) {
|
||||||
|
@ -16,10 +16,11 @@ const attachGlobalListenerTo = window;
|
|||||||
|
|
||||||
export default class SwipeHandler {
|
export default class SwipeHandler {
|
||||||
private element: HTMLElement;
|
private element: HTMLElement;
|
||||||
private onSwipe: (xDiff: number, yDiff: number) => boolean;
|
private onSwipe: (xDiff: number, yDiff: number) => boolean | void;
|
||||||
private verifyTouchTarget: (evt: TouchEvent | MouseEvent) => boolean;
|
private verifyTouchTarget: (evt: TouchEvent | MouseEvent) => boolean;
|
||||||
private onFirstSwipe: () => void;
|
private onFirstSwipe: () => void;
|
||||||
private onReset: () => void;
|
private onReset: () => void;
|
||||||
|
private cursor: 'grabbing' | 'move' = 'grabbing';
|
||||||
|
|
||||||
private hadMove = false;
|
private hadMove = false;
|
||||||
private xDown: number = null;
|
private xDown: number = null;
|
||||||
@ -31,9 +32,14 @@ export default class SwipeHandler {
|
|||||||
verifyTouchTarget?: SwipeHandler['verifyTouchTarget'],
|
verifyTouchTarget?: SwipeHandler['verifyTouchTarget'],
|
||||||
onFirstSwipe?: SwipeHandler['onFirstSwipe'],
|
onFirstSwipe?: SwipeHandler['onFirstSwipe'],
|
||||||
onReset?: SwipeHandler['onReset'],
|
onReset?: SwipeHandler['onReset'],
|
||||||
|
cursor?: SwipeHandler['cursor']
|
||||||
}) {
|
}) {
|
||||||
safeAssign(this, options);
|
safeAssign(this, options);
|
||||||
|
|
||||||
|
this.setListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setListeners() {
|
||||||
if(!isTouchSupported) {
|
if(!isTouchSupported) {
|
||||||
this.element.addEventListener('mousedown', this.handleStart, false);
|
this.element.addEventListener('mousedown', this.handleStart, false);
|
||||||
attachGlobalListenerTo.addEventListener('mouseup', this.reset);
|
attachGlobalListenerTo.addEventListener('mouseup', this.reset);
|
||||||
@ -43,6 +49,16 @@ export default class SwipeHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeListeners() {
|
||||||
|
if(!isTouchSupported) {
|
||||||
|
this.element.removeEventListener('mousedown', this.handleStart, false);
|
||||||
|
attachGlobalListenerTo.removeEventListener('mouseup', this.reset);
|
||||||
|
} else {
|
||||||
|
this.element.removeEventListener('touchstart', this.handleStart, false);
|
||||||
|
attachGlobalListenerTo.removeEventListener('touchend', this.reset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reset = (e?: Event) => {
|
reset = (e?: Event) => {
|
||||||
/* if(e) {
|
/* if(e) {
|
||||||
cancelEvent(e);
|
cancelEvent(e);
|
||||||
@ -101,7 +117,7 @@ export default class SwipeHandler {
|
|||||||
this.hadMove = true;
|
this.hadMove = true;
|
||||||
|
|
||||||
if(!isTouchSupported) {
|
if(!isTouchSupported) {
|
||||||
this.element.style.cursor = 'grabbing';
|
this.element.style.cursor = this.cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.onFirstSwipe) {
|
if(this.onFirstSwipe) {
|
||||||
@ -124,7 +140,8 @@ export default class SwipeHandler {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
/* reset values */
|
/* reset values */
|
||||||
if(this.onSwipe(xDiff, yDiff)) {
|
const onSwipeResult = this.onSwipe(xDiff, yDiff);
|
||||||
|
if(onSwipeResult !== undefined && onSwipeResult) {
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
|
|
||||||
export type GrabEvent = {x: number, y: number, isTouch?: boolean};
|
export type GrabEvent = {x: number, y: number, isTouch?: boolean};
|
||||||
|
|
||||||
export default function attachGrabListeners(element: HTMLElement, onStart: (position: GrabEvent) => void, onMove: (position: GrabEvent) => void, onEnd: (position: GrabEvent) => void) {
|
export default function attachGrabListeners(element: HTMLElement,
|
||||||
|
onStart: (position: GrabEvent) => void,
|
||||||
|
onMove: (position: GrabEvent) => void,
|
||||||
|
onEnd?: (position: GrabEvent) => void) {
|
||||||
// * Mouse
|
// * Mouse
|
||||||
const onMouseMove = (event: MouseEvent) => {
|
const onMouseMove = (event: MouseEvent) => {
|
||||||
onMove({x: event.pageX, y: event.pageY});
|
onMove({x: event.pageX, y: event.pageY});
|
||||||
|
@ -488,11 +488,8 @@
|
|||||||
.progress-line {
|
.progress-line {
|
||||||
--height: 2px;
|
--height: 2px;
|
||||||
--border-radius: 4px;
|
--border-radius: 4px;
|
||||||
|
--thumb-size: .75rem;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
|
||||||
&__seek {
|
|
||||||
--thumb-size: .75rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.default {
|
.default {
|
||||||
border: 0 solid rgba(0, 0, 0, .2);
|
|
||||||
box-shadow: 0 0 20px rgba(0, 0, 0, .2);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
//overflow: hidden;
|
//overflow: hidden;
|
||||||
@ -134,8 +132,12 @@
|
|||||||
&__filled {
|
&__filled {
|
||||||
background: var(--primary-color);
|
background: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__loaded {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
&__loaded, & {
|
& {
|
||||||
background: rgba(255, 255, 255, .38);
|
background: rgba(255, 255, 255, .38);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,15 +243,12 @@
|
|||||||
--color: #fff;
|
--color: #fff;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
|
--thumb-size: 15px;
|
||||||
|
|
||||||
// https://stackoverflow.com/a/4816050
|
// https://stackoverflow.com/a/4816050
|
||||||
html.is-ios & {
|
html.is-ios & {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__seek {
|
|
||||||
--thumb-size: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +267,7 @@ video::-webkit-media-controls-enclosure {
|
|||||||
--color: var(--primary-color);
|
--color: var(--primary-color);
|
||||||
--height: 5px;
|
--height: 5px;
|
||||||
--border-radius: 6px;
|
--border-radius: 6px;
|
||||||
|
--thumb-size: 13px;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
height: var(--height);
|
height: var(--height);
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -285,12 +285,10 @@ video::-webkit-media-controls-enclosure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__seek {
|
&__seek {
|
||||||
--thumb-size: 13px;
|
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -300,63 +298,42 @@ video::-webkit-media-controls-enclosure {
|
|||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
&::-webkit-slider-runnable-track {
|
/* &::-webkit-slider-runnable-track {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-range-track {
|
&::-moz-range-track {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
} */
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-slider-runnable-track {
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 1.3px;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-slider-thumb {
|
&::-webkit-slider-thumb {
|
||||||
height: var(--thumb-size);
|
display: none;
|
||||||
width: var(--thumb-size);
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: var(--color);
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
border: none;
|
|
||||||
//margin-left: -.5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-range-thumb {
|
&::-moz-range-thumb {
|
||||||
height: var(--thumb-size);
|
display: none;
|
||||||
width: var(--thumb-size);
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: var(--color);
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
border: none;
|
|
||||||
//margin-left: -.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-ms-thumb {
|
|
||||||
height: var(--thumb-size);
|
|
||||||
width: var(--thumb-size);
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: var(--color);
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
border: none;
|
|
||||||
//margin-left: -.5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-range-track {
|
&::-moz-range-track {
|
||||||
width: 100%;
|
display: none;
|
||||||
height: 8.4px;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
background: transparent;
|
|
||||||
//border-radius: 1.3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&::-webkit-slider-runnable-track {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* &::-webkit-slider-thumb,
|
||||||
|
&::-moz-range-thumb,
|
||||||
|
&::-moz-range-track,
|
||||||
|
&::-webkit-slider-runnable-track {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
background: transparent;
|
||||||
|
border-color: transparent;
|
||||||
|
color: transparent;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
&__filled {
|
&__filled {
|
||||||
@ -366,6 +343,20 @@ video::-webkit-media-controls-enclosure {
|
|||||||
&:not(.progress-line__loaded) {
|
&:not(.progress-line__loaded) {
|
||||||
background-color: var(--color);
|
background-color: var(--color);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
height: var(--thumb-size);
|
||||||
|
width: var(--thumb-size);
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--color);
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(calc(var(--thumb-size) / 2), -50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,11 +365,19 @@ video::-webkit-media-controls-enclosure {
|
|||||||
background-color: var(--secondary-color);
|
background-color: var(--secondary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__seek, &__filled, &__loaded {
|
&__seek,
|
||||||
|
&__filled,
|
||||||
|
&__loaded {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include animation-level(2) {
|
||||||
|
&.with-transition .progress-line__filled {
|
||||||
|
transition: width .2s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,17 +1123,14 @@
|
|||||||
|
|
||||||
.progress-line {
|
.progress-line {
|
||||||
--height: 2px;
|
--height: 2px;
|
||||||
|
--color: var(--primary-color);
|
||||||
--border-radius: 4px;
|
--border-radius: 4px;
|
||||||
|
--thumb-size: 12px;
|
||||||
background-color: #e6ecf0;
|
background-color: #e6ecf0;
|
||||||
|
|
||||||
&__filled {
|
&__filled {
|
||||||
background-color: var(--primary-color);
|
background-color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__seek {
|
|
||||||
--thumb-color: var(--primary-color);
|
|
||||||
--thumb-size: 12px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$inactive-opacity: .4;
|
||||||
|
|
||||||
.media-viewer {
|
.media-viewer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -119,7 +121,7 @@
|
|||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
z-index: 5;
|
z-index: 4;
|
||||||
bottom: .75rem;
|
bottom: .75rem;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -151,7 +153,7 @@
|
|||||||
|
|
||||||
.media-viewer-whole.active & {
|
.media-viewer-whole.active & {
|
||||||
html.no-touch & {
|
html.no-touch & {
|
||||||
opacity: .4;
|
opacity: $inactive-opacity;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@ -255,7 +257,7 @@
|
|||||||
|
|
||||||
&-mover/* , &-canvas */ {
|
&-mover/* , &-canvas */ {
|
||||||
position: fixed!important;
|
position: fixed!important;
|
||||||
z-index: 4;
|
// z-index: 4;
|
||||||
//transition: .5s all;
|
//transition: .5s all;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -435,14 +437,15 @@
|
|||||||
padding: 0 1.25rem;
|
padding: 0 1.25rem;
|
||||||
|
|
||||||
.btn-icon, .media-viewer-author {
|
.btn-icon, .media-viewer-author {
|
||||||
color: #8b8b8b;
|
color: #fff;
|
||||||
|
opacity: $inactive-opacity;
|
||||||
|
|
||||||
@include animation-level(2) {
|
@include animation-level(2) {
|
||||||
transition: color var(--open-duration) ease-in-out;
|
transition: opacity var(--open-duration) ease-in-out, color var(--open-duration) ease-in-out, background-color var(--open-duration) ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include hover() {
|
@include hover() {
|
||||||
color: #fff;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,6 +533,9 @@
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
.btn-menu-toggle {
|
.btn-menu-toggle {
|
||||||
|
color: rgba(255, 255, 255, $inactive-opacity);
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
&.menu-open {
|
&.menu-open {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: rgba(112, 117, 121, .2) !important;
|
background-color: rgba(112, 117, 121, .2) !important;
|
||||||
@ -544,6 +550,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-movers {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
@include animation-level(2) {
|
||||||
|
transition: transform var(--open-duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* &-switchers {
|
/* &-switchers {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: $large-screen;
|
width: $large-screen;
|
||||||
@ -553,6 +572,74 @@
|
|||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tgico-zoom {
|
||||||
|
&:before {
|
||||||
|
content: $tgico-zoomout;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.zoom-in:before {
|
||||||
|
content: $tgico-zoomin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-container {
|
||||||
|
width: 17.125rem;
|
||||||
|
height: 3.375rem;
|
||||||
|
background-color: rgba(0, 0, 0, .4);
|
||||||
|
border-radius: $border-radius-big;
|
||||||
|
padding: .5rem;
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1.25rem;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
z-index: 5;
|
||||||
|
|
||||||
|
@include animation-level(2) {
|
||||||
|
transition: opacity var(--open-duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-icon {
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&.inactive {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: $inactive-opacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-line {
|
||||||
|
--color: #fff;
|
||||||
|
--height: 2px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
margin: 0 1px;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.is-visible),
|
||||||
|
.media-viewer-whole:not(.active) & {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-visible {
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
& ~ .media-viewer-caption {
|
||||||
|
opacity: 0 !important;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.overlays {
|
.overlays {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user