├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── app-screenshot.png ├── package.json ├── src ├── index.ts ├── zoom-area.component.ts ├── zoom-area.module.ts ├── zoom-area.provider.ts └── zoom-area.scss └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | aot 4 | .idea 5 | .DS_STORE 6 | .DX_STORE 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | node_modules 3 | .gitignore 4 | .npmignore 5 | tsconfig.json 6 | .idea 7 | aot 8 | app-screenshot.png 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## 1.0.17 (2019-04-22) 3 | 4 | ### Feature 5 | 6 | * **New version:** 7 | Introduces the features to release a new version for a Ionic 4. 8 | 9 | 10 | ## 1.0.16 (2018-03-26) 11 | 12 | ### Bug Fixes 13 | 14 | * **AOT Compilation:** 15 | [#10](https://github.com/leonardosalles/ionic2-zoom-area/issues/10) - Fixes the problem during --prod build with Ionic. 16 | 17 | 18 | ## 1.0.12 (2017-11-28) 19 | 20 | ### Bug Fixes 21 | 22 | * **Known Issue:** 23 | It fixes a known issue that prevent user to start vertical pan. 24 | 25 | 26 | ## 1.0.11 (2017-11-23) 27 | 28 | ### Bug Fixes 29 | 30 | * **LazyLoading:** 31 | Closes [#8](https://github.com/leonardosalles/ionic2-zoom-area/issues/8) - Fix ZoomAreaProvider not available 32 | 33 | 34 | ## 1.0.10 (2017-11-23) 35 | 36 | ### Bug Fixes 37 | 38 | * **LazyLoading:** 39 | Closes [#6](https://github.com/leonardosalles/ionic2-zoom-area/issues/6) - Allow module to be used with LazyLoading 40 | 41 | * **Feature Request:** 42 | Closes [#2](https://github.com/leonardosalles/ionic2-zoom-area/issues/2) - Add support to set center if zoom scale is greater than 1 43 | 44 | 45 | 46 | ## 1.0.9 (2017-10-17) 47 | Release the kraken 48 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Leonardo Salles 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![npm](https://img.shields.io/npm/l/ionic2-zoom-area.svg)](https://www.npmjs.com/package/ionic2-zoom-area) 2 | [![npm](https://img.shields.io/npm/dt/ionic2-zoom-area.svg)](https://www.npmjs.com/package/ionic2-zoom-area) 3 | [![npm](https://img.shields.io/npm/dm/ionic2-zoom-area.svg)](https://www.npmjs.com/package/ionic2-zoom-area) 4 | 5 | # A zoom area for Ionic 2 and 3 :) 6 | 7 | IMPORTANT: New release for Ionic 4 will be release here as a new Version of the core component. 8 | 9 | IMPORTANT: Versions 1.0.12 and 1.0.13 will not work as expected, please use <=1.0.11 or >=1.0.14 instead. 10 | 11 | A zoom area component with pinch support to zoom any element in page 12 | 13 | To see this in action, checkout the [example project here](https://github.com/leonardosalles/ionic2-zoom-area-example). 14 | 15 | IMPORTANT: This module requires Angular Animations and should be included in the app module. 16 | 17 |
18 | 19 | ![Screenshot](app-screenshot.png?raw=true) 20 | 21 | 22 |

23 | 24 | 25 | - [Quick Example](#quick-example) 26 | - [Installation](#installation) 27 | - [Usage](#usage) 28 | - [`zoom-area` Component](#zoom-area-component) 29 | - [Examples](#examples) 30 | 31 |


32 | 33 | # Quick Example 34 | ```html 35 | 36 |
37 | zoom it 38 |
39 | or 40 | zoom it 41 |
42 | ``` 43 | 44 |


45 | 46 | # Installation 47 | ## Add Angular Animations 48 | ```shell 49 | npm i --save @angular/animations 50 | ``` 51 | 52 | ## Import BrowserAnimationsModule in your app's module(s) 53 | ```ts 54 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 55 | ``` 56 | 57 | And then 58 | 59 | ```ts 60 | imports: [ 61 | ... 62 | BrowserAnimationsModule, 63 | ... 64 | ] 65 | ``` 66 | 67 | ## Install the module via NPM 68 | ```shell 69 | npm i --save ionic2-zoom-area 70 | ``` 71 | 72 | ## Import it in your app's module(s) 73 | 74 | Import `ZoomAreaModule.forRoot()` in your app's main module 75 | 76 | ```ts 77 | import { ZoomAreaModule } from 'ionic2-zoom-area'; 78 | 79 | @NgModule({ 80 | ... 81 | imports: [ 82 | ... 83 | ZoomAreaModule.forRoot() 84 | ], 85 | ... 86 | }) 87 | export class AppModule {} 88 | ``` 89 | 90 | If your app uses lazy loading, you need to import `ZoomAreaModule` in your shared module or child modules: 91 | ```ts 92 | import { ZoomAreaModule } from 'ionic2-zoom-area'; 93 | 94 | @NgModule({ 95 | ... 96 | imports: [ 97 | ... 98 | ZoomAreaModule 99 | ], 100 | ... 101 | }) 102 | export class SharedModule {} 103 | ``` 104 | 105 |


106 | 107 | # Usage 108 | 109 | 110 | ## `zoom-area` Component 111 | 112 | ### Inputs 113 | 114 | #### scale 115 | _(optional)_ _(two-way)_ The scale of your initial zoom. Defaults to `1`. 116 | 117 | #### controls 118 | _(optional)_ _(two-way)_ It allow you to hide or show zoom controls. Defaults to `true`. 119 | 120 | 121 | ### Outputs 122 | 123 | #### `afterZoomIn` 124 | Listen to this event to be notified when the user interact with zoom in. 125 | 126 | #### `afterZoomOut` 127 | Listen to this event to be notified when the user interact with zoom out. 128 | 129 |

130 | 131 | ## `ZoomAreaProvider` Provider 132 | 133 | ### notifyScroll 134 | ```ts 135 | notifyScroll(): void 136 | ``` 137 | It broadcast an event when user scroll content inside zoom area. 138 | 139 | ### onScroll$ 140 | ```ts 141 | onScroll$: Observable 142 | ``` 143 | It allows you to listen for a scroll event inside your zoom area. You can use it to collapse you header for example. 144 | 145 | ```ts 146 | this.zoomAreaProvider.onScroll$.subscribe(state => { 147 | if (state === this.zoomAreaProvider.SCROLL_STATE.COLLAPSED) { 148 | console.log('Hide header'); 149 | } 150 | 151 | if (state === this.zoomAreaProvider.SCROLL_STATE.EXPANDED) { 152 | console.log('Show header'); 153 | } 154 | }); 155 | ``` 156 | 157 | ### scrollState$ 158 | ```ts 159 | scrollState$: Observable 160 | ``` 161 | It allows you to listen for a change in scroll state. 162 | ```ts 163 | this.zoomAreaProvider.scrollState$.subscribe(state => { 164 |  console.log('Do whatever you want when scrollState change'); 165 | }); 166 | ``` 167 | 168 | ### setCenter (x: number, y: number) 169 | ```ts 170 | setCenter: Function 171 | ``` 172 | It allows you to change the position of the zoom manually if zoom scale is greather than 1. 173 | ```ts 174 | this.zoomAreaProvider.setCenter(x, y); 175 | this.zoomAreaProvider.setCenter(20, 50); 176 | ``` 177 | 178 | # Examples 179 | 180 | ## Basic example 181 | 182 | ## Example with methods 183 | ```html 184 | 185 |
Zoom It
186 | or 187 | Zoom It 188 |
189 | ``` 190 | 191 |

192 | 193 | ## Known Issues 🤬 194 | - ✅(Fixed in 1.0.12) Vertical pan is in conflict with scroll event and are not fired like horizontal pan. 195 | 196 | 197 | 198 |

199 | 200 | ## Roadmap 201 | - ✅(Fixed in 1.0.10) - Add support to move center of zoom 202 | 203 |

204 | ## Contribution 205 | - **Having an issue**? or looking for support? [Open an issue](https://github.com/leonardosalles/ionic2-zoom-area/issues/new) and we will get you the help you need. 206 | - Got a **new feature or a bug fix**? Fork the repo, make your changes, and submit a pull request. 207 | 208 | ## Support this project 209 | If you find this project useful, please star the repo to let people know that it's reliable. Also, share it with friends and colleagues that might find this useful as well. Thank you :smile: 210 | 211 | ## Special Thanks ## 212 | We would like to thank [JetBrains](http://www.jetbrains.com) for supporting this project by offering open-source license of their [IntelliJ IDE](http://www.jetbrains.com/idea/) to us. 213 | -------------------------------------------------------------------------------- /app-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonardosalles/ionic2-zoom-area/f2f31b77e9efc936df53a9b6c3b806537caa8b0a/app-screenshot.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic2-zoom-area", 3 | "version": "1.0.16", 4 | "description": "A zoom area component with pinch and pan support.", 5 | "main": "dist/index.js", 6 | "typings": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "rm -rf aot dist && ngc", 9 | "postbuild": "npm run copy:scss", 10 | "copy:scss": "cp src/zoom-area.scss dist/", 11 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", 12 | "postchangelog": "git commit -am \"chore(): update changelog\"", 13 | "shipit": "npm run build && npm publish" 14 | }, 15 | "author": "Leonardo Salles ", 16 | "license": "MIT", 17 | "repository": "https://github.com/leonardosalles/ionic2-zoom-area", 18 | "dependencies": { 19 | "@angular/animations": "5.1.3", 20 | "@angular/common": "5.1.3", 21 | "@angular/compiler": "5.1.3", 22 | "@angular/compiler-cli": "5.1.3", 23 | "@angular/core": "10.2.5", 24 | "@angular/forms": "5.1.3", 25 | "@angular/http": "5.1.3", 26 | "@angular/platform-browser": "5.1.3", 27 | "@angular/platform-browser-dynamic": "5.1.3", 28 | "conventional-changelog-cli": "^1.3.4", 29 | "ionicons": "3.0.0", 30 | "rxjs": "5.5.2", 31 | "zone.js": "0.8.18", 32 | "ionic-angular": "3.9.2" 33 | }, 34 | "devDependencies": { 35 | "typescript": "2.5.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './zoom-area.component'; 2 | export * from './zoom-area.provider'; 3 | export * from './zoom-area.module'; -------------------------------------------------------------------------------- /src/zoom-area.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ViewChild, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core'; 2 | import { trigger, state, style, transition, animate } from '@angular/animations'; 3 | import { Gesture, Content, RootNode } from 'ionic-angular'; 4 | import { ZoomAreaProvider } from './zoom-area.provider'; 5 | 6 | @Component({ 7 | selector: 'zoom-area', 8 | template: ` 9 | 10 |
11 |
12 | 13 |
14 |
15 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | 29 |
30 | `, 31 | animations: [ 32 | trigger('visibilityChanged', [ 33 | state('shown', style({ opacity: 1, display: 'block' })), 34 | state('hidden', style({ opacity: 0, display: 'none' })), 35 | transition('shown => hidden', animate('300ms')), 36 | transition('hidden => shown', animate('300ms')), 37 | ]) 38 | ] 39 | }) 40 | export class ZoomAreaComponent implements OnChanges { 41 | @ViewChild('zoomAreaRoot') zoom; 42 | @ViewChild(Content) content: Content; 43 | 44 | @Output() afterZoomIn = new EventEmitter(); 45 | @Output() afterZoomOut = new EventEmitter(); 46 | 47 | @Input() controls: boolean; 48 | @Output() controlsChanged = new EventEmitter(); 49 | 50 | @Input() scale: number; 51 | @Output() scaleChanged = new EventEmitter(); 52 | 53 | zoomControlsState; 54 | zoomRootElement; 55 | gesture; 56 | 57 | constructor ( 58 | public zoomAreaProvider: ZoomAreaProvider 59 | ) { 60 | this.zoomControlsState = 'hidden'; 61 | } 62 | 63 | ngOnChanges (changes: SimpleChanges) { 64 | if ('controls' in changes) { 65 | let showControls = changes['controls']; 66 | 67 | if (showControls && showControls.currentValue) { 68 | this.zoomControlsState = 'shown'; 69 | } else { 70 | this.zoomControlsState = 'hidden'; 71 | } 72 | } 73 | 74 | if ('scale' in changes) { 75 | let scaleValue = changes['scale']; 76 | 77 | if (scaleValue && scaleValue.currentValue && scaleValue.currentValue === 1) { 78 | this.zoomReset(); 79 | } 80 | } 81 | } 82 | 83 | ngAfterViewInit () { 84 | this.content.ionScroll.subscribe((data)=>{ 85 | this.zoomAreaProvider.notifyScroll(data); 86 | }); 87 | 88 | this._pinchZoom(this.zoom.nativeElement, this.content); 89 | 90 | // Watch for user setCenter call 91 | let self = this; 92 | this.zoomAreaProvider.centerChanged$.subscribe(coords => { 93 | if (self.zoomConfig.scale === 1) { 94 | return; 95 | } 96 | 97 | self.setCoor(coords.x, coords.y); 98 | self.transform(coords.x, coords.y); 99 | }); 100 | } 101 | 102 | zoomConfig = { 103 | ow: 0, 104 | oh: 0, 105 | original_x: 0, 106 | original_y: 0, 107 | max_x: 0, 108 | max_y: 0, 109 | min_x: 0, 110 | min_y: 0, 111 | x: 0, 112 | y: 0, 113 | last_x: 0, 114 | last_y: 0, 115 | scale: 1, 116 | base: 1, 117 | }; 118 | 119 | toggleZoomControls () { 120 | this.zoomControlsState = this.zoomControlsState === 'shown' ? 'hidden' : 'shown'; 121 | } 122 | 123 | zoomIn () { 124 | this.zoomConfig.scale += 1; 125 | 126 | if (this.zoomConfig.scale > 1) { 127 | this.zoomAreaProvider.notifyScrollState(this.zoomAreaProvider.SCROLL_STATE.COLAPSED); 128 | } 129 | 130 | if (this.zoomConfig.scale > 4) { 131 | this.zoomConfig.scale = 4; 132 | } 133 | 134 | this.transform(); 135 | this.afterZoomIn.emit(); 136 | } 137 | 138 | zoomOut (reset?) { 139 | if (!this.zoomRootElement) { 140 | return; 141 | } 142 | 143 | this.zoomConfig.scale -= 1; 144 | 145 | if (this.zoomConfig.scale < 1) { 146 | this.zoomConfig.scale = 1; 147 | } 148 | 149 | if (this.zoomConfig.scale === 1) { 150 | reset = true; 151 | this.zoomAreaProvider.notifyScrollState(this.zoomAreaProvider.SCROLL_STATE.NORMAL); 152 | } 153 | 154 | reset ? this.transform(0.1, 0.1) : this.transform(); 155 | 156 | this.afterZoomOut.emit(); 157 | } 158 | 159 | zoomReset () { 160 | this.zoomConfig.scale = 1; 161 | if (this.content && this.content.scrollTop) { 162 | this.content.scrollTop = 0; 163 | } 164 | this.zoomOut(true); 165 | } 166 | 167 | private _pinchZoom(elm: HTMLElement, content: Content): void { 168 | this.zoomRootElement = elm; 169 | this.gesture = new Gesture(this.zoomRootElement); 170 | 171 | for (let i = 0; i < elm.children.length; i++) { 172 | let c = elm.children.item(i); 173 | this.zoomConfig.ow = c.offsetWidth; 174 | this.zoomConfig.oh += c.offsetHeight; 175 | } 176 | 177 | this.zoomConfig.original_x = content.contentWidth - this.zoomConfig.ow; 178 | this.zoomConfig.original_y = content.contentHeight - this.zoomConfig.oh; 179 | this.zoomConfig.max_x = this.zoomConfig.original_x; 180 | this.zoomConfig.max_y = this.zoomConfig.original_y; 181 | this.zoomConfig.base = this.zoomConfig.scale; 182 | 183 | this.gesture.listen(); 184 | this.gesture.on('pan', this.onPan.bind(this)); 185 | this.gesture.on('panend', this.onPanend.bind(this)); 186 | this.gesture.on('pancancel',this. onPanend.bind(this)); 187 | this.gesture.on('tap', this.onTap.bind(this)); 188 | this.gesture.on('pinch', this.onPinch.bind(this)); 189 | this.gesture.on('pinchend', this.onPinchend.bind(this)); 190 | this.gesture.on('pinchcancel', this.onPinchend.bind(this)); 191 | } 192 | 193 | onPan(ev) { 194 | if (this.zoomConfig.scale === 1) { 195 | return; 196 | } 197 | 198 | this.setCoor(ev.deltaX, ev.deltaY); 199 | this.transform(); 200 | } 201 | 202 | onPanend() { 203 | this.zoomConfig.last_x = this.zoomConfig.x; 204 | this.zoomConfig.last_y = this.zoomConfig.y; 205 | } 206 | 207 | onTap(ev) { 208 | if (ev && ev.tapCount > 1) { 209 | let reset = false; 210 | this.zoomConfig.scale += .5; 211 | if (this.zoomConfig.scale > 2) { 212 | this.zoomConfig.scale = 1; 213 | reset = true; 214 | } 215 | 216 | this.setBounds(); 217 | reset ? this.transform(this.zoomConfig.max_x/2, this.zoomConfig.max_y/2) : this.transform(); 218 | } 219 | } 220 | 221 | onPinch(ev) { 222 | this.zoomConfig.scale = this.zoomConfig.base + (ev.scale * this.zoomConfig.scale - this.zoomConfig.scale)/this.zoomConfig.scale 223 | this.setBounds(); 224 | this.transform(); 225 | } 226 | 227 | onPinchend(ev) { 228 | if (this.zoomConfig.scale > 4) { 229 | this.zoomConfig.scale = 4; 230 | } 231 | 232 | if (this.zoomConfig.scale < 1) { 233 | this.zoomConfig.scale = 1; 234 | } 235 | 236 | this.zoomConfig.base = this.zoomConfig.scale; 237 | this.setBounds(); 238 | this.transform(); 239 | } 240 | 241 | setBounds() { 242 | let scaled_x = Math.ceil((this.zoomRootElement.offsetWidth * this.zoomConfig.scale - this.zoomRootElement.offsetWidth) / 2); 243 | let scaled_y = Math.ceil((this.zoomRootElement.offsetHeight * this.zoomConfig.scale - this.zoomRootElement.offsetHeight) / 2); 244 | 245 | let overflow_x = Math.ceil(this.zoomConfig.original_x * this.zoomConfig.scale - this.zoomConfig.original_x); 246 | let overflow_y = Math.ceil(this.zoomConfig.oh * this.zoomConfig.scale - this.zoomConfig.oh); 247 | 248 | this.zoomConfig.max_x = this.zoomConfig.original_x - scaled_x + overflow_x; 249 | this.zoomConfig.min_x = 0 + scaled_x; 250 | 251 | this.zoomConfig.max_y = this.zoomConfig.original_y + scaled_y - overflow_y; 252 | this.zoomConfig.min_y = 0 + scaled_y; 253 | 254 | this.setCoor(-scaled_x, scaled_y); 255 | } 256 | 257 | setCoor(xx: number, yy: number) { 258 | const compensation = this.zoomConfig.scale === 2 ? 1.05 : (this.zoomConfig.scale / 1.25); 259 | this.zoomConfig.x = Math.min(Math.max((this.zoomConfig.last_x + xx), this.zoomConfig.max_x * compensation), this.zoomConfig.min_x * compensation); 260 | this.zoomConfig.y = Math.min(Math.max((this.zoomConfig.last_y + yy), this.zoomConfig.max_y * compensation), this.zoomConfig.min_y * compensation); 261 | } 262 | 263 | transform(xx?: number, yy?: number) { 264 | this.zoomRootElement.style.transform = `translate3d(${xx || this.zoomConfig.x}px, ${yy || this.zoomConfig.y}px, 0) scale3d(${this.zoomConfig.scale}, ${this.zoomConfig.scale}, 1)`; 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /src/zoom-area.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ModuleWithProviders } from '@angular/core'; 2 | import { IonicModule } from 'ionic-angular'; 3 | import { ZoomAreaComponent } from './zoom-area.component'; 4 | import { ZoomAreaProvider } from './zoom-area.provider'; 5 | 6 | @NgModule({ 7 | declarations: [ 8 | ZoomAreaComponent 9 | ], 10 | imports: [ 11 | IonicModule 12 | ], 13 | exports: [ 14 | ZoomAreaComponent 15 | ], 16 | providers: [ 17 | ZoomAreaProvider 18 | ] 19 | }) 20 | export class ZoomAreaModule { 21 | static forRoot(): ModuleWithProviders { 22 | return { 23 | ngModule: ZoomAreaModule, 24 | providers: [ 25 | ZoomAreaProvider 26 | ] 27 | }; 28 | } 29 | } -------------------------------------------------------------------------------- /src/zoom-area.provider.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Observable, Subject } from 'rxjs/Rx'; 3 | 4 | @Injectable() 5 | export class ZoomAreaProvider { 6 | SCROLL_STATE = { 7 | NORMAL: 'scrollNormal', 8 | COLAPSED: 'scrollColapsed' 9 | }; 10 | 11 | private _onScroll = new Subject(); 12 | onScroll$ = this._onScroll.asObservable(); 13 | 14 | private _scrollState = new Subject(); 15 | scrollState$ = this._scrollState.asObservable(); 16 | 17 | private _centerChanged = new Subject(); 18 | centerChanged$ = this._centerChanged.asObservable(); 19 | 20 | constructor () {} 21 | 22 | notifyScroll (data) { 23 | this._onScroll.next(data); 24 | } 25 | 26 | notifyScrollState (data) { 27 | this._scrollState.next(data); 28 | } 29 | 30 | setCenter (x: number, y: number) { 31 | this._centerChanged.next({x: x, y: y}); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/zoom-area.scss: -------------------------------------------------------------------------------- 1 | zoom-area { 2 | .scroll-content { 3 | overflow: hidden !important; 4 | touch-action: none !important; 5 | } 6 | 7 | .zoom { 8 | width: 100% !important; 9 | height: 100% !important; 10 | touch-action: none !important; 11 | position: fixed; 12 | 13 | .fit { 14 | touch-action: none !important; 15 | } 16 | } 17 | 18 | .btn-zoom { 19 | width: 35px; 20 | height: 35px !important; 21 | padding: 10px; 22 | margin-bottom: 10px; 23 | } 24 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "es2015", 4 | "target": "es5", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "inlineSources": true, 8 | "declaration": true, 9 | "noImplicitAny": false, 10 | "experimentalDecorators": true, 11 | "skipLibCheck": true, 12 | "lib": [ 13 | "dom", 14 | "es2015" 15 | ], 16 | "outDir": "dist" 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | "dist" 21 | ], 22 | "angularCompilerOptions": { 23 | "genDir": "aot" 24 | } 25 | } --------------------------------------------------------------------------------