UNPKG

oda-framework

Version:

It's an ES Progressive Framework based on the technology of Web Components and designed especially for creating custom UI/UX of any complexity for web and cross-platform PWA mobile applications.

137 lines 4.6 kB
ODA({is: 'oda-image-viewer', imports: '@oda/button', template: /*html*/` <style> :host { @apply --vertical; @apply --flex; height: 100%; background-color: #242424; overflow: hidden; } :host > .img { cursor: grab; } :host > .img:active { cursor: grabbing; } :host .image { width: 100%; background: no-repeat center; background-size: contain; } </style> <div class="horizontal center" style="z-index: 1;" @dblclick.stop> <oda-button icon="image:rotate-left" fill="white" @tap="_rotateLeft"></oda-button> <oda-button icon="image:rotate-right" fill="white" @tap="_rotateRight"></oda-button> <oda-button icon="icons:file-download" fill="white" @tap="_download"></oda-button> <oda-button icon="icons:fullscreen" fill="white" @tap="setFullscreen"></oda-button> </div> <div id="img" class="vertical img flex" ~style="_imageStyle"> <div class="image flex" ~style="\`background-image: url('\${src}');\`"></div> </div> `, $public: { src: { $def: '', set() { this._reset(); }, }, alt: '', title: '', _x: 0, _y: 0, _scale: 1, _rotate: 0, _imageStyle: { $type: String, get() { return `transform: translate3d(${this._x || 0}px, ${this._y || 0}px, 0) scale(${this._scale || 0}) rotate(${this._rotate || 0}deg)`; } } }, $listeners: { 'track': '_onTrack', 'wheel': '_onScroll', 'dblclick': '_reset' }, _onTrack(e, d) { if (!this.img) return; switch (d.state) { case 'start': { this._x += d.ddx || 0; this._y += d.ddy || 0; } break; case 'track': { this._x += d.ddx || 0; this._y += d.ddy || 0; } break; case 'end': { const img = this.img; const halfWidth = img.offsetWidth * 0.5 * this._scale; const halfHeight = img.offsetHeight * 0.5 * this._scale; const x = Math.max(Math.min(this._x + (d.ddx || 0), halfWidth), -halfWidth); const y = Math.max(Math.min(this._y + (d.ddy || 0), halfHeight), -halfHeight); this._x = x; this._y = y; } } }, get img(){ return this.$('img'); }, _onScroll(e) { const img = this.img; if (!img) return const scale = Math.max(1, this._scale + -e.deltaY * 0.005); if (scale === 1) { this._reset(); } else { this._x = this._x / (img.offsetWidth * this._scale / (img.offsetWidth * scale) || 1); this._y = this._y / (img.offsetHeight * this._scale / (img.offsetHeight * scale) || 1); } this._scale = scale; }, _rotateLeft() { this._rotate -= 90; }, _rotateRight() { this._rotate += 90; }, _download() { const link = document.createElement('a'); link.setAttribute('href', `${this.src}?method=download`); link.setAttribute('download', 'download'); link.click(); }, _reset(withRotate) { this._x = 0; this._y = 0; this._scale = 1; if (withRotate) this.rotate = 0; }, setFullscreen() { this.fullscreenMode = !this.fullscreenMode; const element = this; if (this.fullscreenMode) { if (element.requestFullscreen) { element.requestFullscreen(); } else if (element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if (element.webkitRequestFullscreen) { element.webkitRequestFullscreen(); } else if (element.msRequestFullscreen) { element.msRequestFullscreen(); } } else { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } } } })