format all files with prettier

This commit is contained in:
Konstantin Schütte 2022-02-07 13:46:52 +01:00
parent ca85b6872a
commit ec9b2c163a
42 changed files with 1314 additions and 1442 deletions

View file

@ -12,302 +12,257 @@ https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FA
Happy linting! 💖
*/
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
env: {
browser: true,
es6: true,
node: true,
},
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
extends: ['plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
"plugins": [
"eslint-plugin-import",
"eslint-plugin-jsdoc",
"@angular-eslint/eslint-plugin",
"@angular-eslint/eslint-plugin-template",
"eslint-plugin-prefer-arrow",
"@typescript-eslint",
"@typescript-eslint/tslint"
plugins: [
'eslint-plugin-import',
'eslint-plugin-jsdoc',
'@angular-eslint/eslint-plugin',
'@angular-eslint/eslint-plugin-template',
'eslint-plugin-prefer-arrow',
'@typescript-eslint',
'@typescript-eslint/tslint',
],
"rules": {
"@angular-eslint/component-class-suffix": "error",
"@angular-eslint/component-selector": [
"error",
rules: {
'@angular-eslint/component-class-suffix': 'error',
'@angular-eslint/component-selector': [
'error',
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
"@angular-eslint/contextual-lifecycle": "error",
"@angular-eslint/directive-class-suffix": "error",
"@angular-eslint/directive-selector": [
"error",
'@angular-eslint/contextual-lifecycle': 'error',
'@angular-eslint/directive-class-suffix': 'error',
'@angular-eslint/directive-selector': [
'error',
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
"@angular-eslint/no-conflicting-lifecycle": "error",
"@angular-eslint/no-host-metadata-property": "error",
"@angular-eslint/no-input-rename": "error",
"@angular-eslint/no-inputs-metadata-property": "error",
"@angular-eslint/no-output-native": "error",
"@angular-eslint/no-output-on-prefix": "error",
"@angular-eslint/no-output-rename": "error",
"@angular-eslint/no-outputs-metadata-property": "error",
"@angular-eslint/template/banana-in-box": "error",
"@angular-eslint/template/eqeqeq": "error",
"@angular-eslint/template/no-negated-async": "error",
"@angular-eslint/use-lifecycle-interface": "error",
"@angular-eslint/use-pipe-transform-interface": "error",
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "off",
"@typescript-eslint/ban-types": [
"error",
'@angular-eslint/no-conflicting-lifecycle': 'error',
'@angular-eslint/no-host-metadata-property': 'error',
'@angular-eslint/no-input-rename': 'error',
'@angular-eslint/no-inputs-metadata-property': 'error',
'@angular-eslint/no-output-native': 'error',
'@angular-eslint/no-output-on-prefix': 'error',
'@angular-eslint/no-output-rename': 'error',
'@angular-eslint/no-outputs-metadata-property': 'error',
'@angular-eslint/template/banana-in-box': 'error',
'@angular-eslint/template/eqeqeq': 'error',
'@angular-eslint/template/no-negated-async': 'error',
'@angular-eslint/use-lifecycle-interface': 'error',
'@angular-eslint/use-pipe-transform-interface': 'error',
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/array-type': 'off',
'@typescript-eslint/ban-types': [
'error',
{
"types": {
"Object": {
"message": "Avoid using the `Object` type. Did you mean `object`?"
types: {
Object: {
message: 'Avoid using the `Object` type. Did you mean `object`?',
},
"Function": {
"message": "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."
Function: {
message: 'Avoid using the `Function` type. Prefer a specific function type, like `() => void`.',
},
"Boolean": {
"message": "Avoid using the `Boolean` type. Did you mean `boolean`?"
Boolean: {
message: 'Avoid using the `Boolean` type. Did you mean `boolean`?',
},
"Number": {
"message": "Avoid using the `Number` type. Did you mean `number`?"
Number: {
message: 'Avoid using the `Number` type. Did you mean `number`?',
},
"String": {
"message": "Avoid using the `String` type. Did you mean `string`?"
String: {
message: 'Avoid using the `String` type. Did you mean `string`?',
},
"Symbol": {
"message": "Avoid using the `Symbol` type. Did you mean `symbol`?"
}
}
}
Symbol: {
message: 'Avoid using the `Symbol` type. Did you mean `symbol`?',
},
},
},
],
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/dot-notation": "error",
"@typescript-eslint/indent": [
"error",
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/indent': [
'error',
4,
{
"FunctionDeclaration": {
"parameters": "first"
FunctionDeclaration: {
parameters: 'first',
},
"FunctionExpression": {
"parameters": "first"
}
}
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "semi",
"requireLast": true
FunctionExpression: {
parameters: 'first',
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
},
],
"@typescript-eslint/member-ordering": "error",
"@typescript-eslint/naming-convention": "error",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": [
"error",
'@typescript-eslint/member-delimiter-style': [
'error',
{
"ignoreParameters": true
}
multiline: {
delimiter: 'semi',
requireLast: true,
},
singleline: {
delimiter: 'semi',
requireLast: false,
},
},
],
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-shadow": [
"error",
'@typescript-eslint/member-ordering': 'error',
'@typescript-eslint/naming-convention': 'error',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-inferrable-types': [
'error',
{
"hoist": "all"
}
ignoreParameters: true,
},
],
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/quotes": [
"error",
"single"
],
"@typescript-eslint/semi": [
"error",
"always"
],
"@typescript-eslint/triple-slash-reference": [
"error",
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-parameter-properties': 'off',
'@typescript-eslint/no-shadow': [
'error',
{
"path": "always",
"types": "prefer-import",
"lib": "always"
}
hoist: 'all',
},
],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unified-signatures": "error",
"arrow-body-style": "error",
"complexity": "off",
"constructor-super": "error",
"curly": "error",
"dot-notation": "error",
"eol-last": "error",
"eqeqeq": [
"error",
"smart"
],
"guard-for-in": "error",
"id-denylist": [
"error",
"any",
"Number",
"number",
"String",
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
],
"id-match": "error",
"import/no-deprecated": "warn",
"indent": "error",
"jsdoc/check-alignment": "error",
"jsdoc/check-indentation": "error",
"jsdoc/newline-after-description": "error",
"jsdoc/no-types": "error",
"max-classes-per-file": "off",
"max-len": [
"error",
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/quotes': ['error', 'single'],
'@typescript-eslint/semi': ['error', 'always'],
'@typescript-eslint/triple-slash-reference': [
'error',
{
"code": 140
}
path: 'always',
types: 'prefer-import',
lib: 'always',
},
],
"new-parens": "error",
"no-bitwise": "error",
"no-caller": "error",
"no-cond-assign": "error",
"no-console": [
"error",
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/unified-signatures': 'error',
'arrow-body-style': 'error',
complexity: 'off',
'constructor-super': 'error',
curly: 'error',
'dot-notation': 'error',
'eol-last': 'error',
eqeqeq: ['error', 'smart'],
'guard-for-in': 'error',
'id-denylist': ['error', 'any', 'Number', 'number', 'String', 'string', 'Boolean', 'boolean', 'Undefined', 'undefined'],
'id-match': 'error',
'import/no-deprecated': 'warn',
indent: 'error',
'jsdoc/check-alignment': 'error',
'jsdoc/check-indentation': 'error',
'jsdoc/newline-after-description': 'error',
'jsdoc/no-types': 'error',
'max-classes-per-file': 'off',
'max-len': [
'error',
{
"allow": [
"log",
"warn",
"dir",
"timeLog",
"assert",
"clear",
"count",
"countReset",
"group",
"groupEnd",
"table",
"dirxml",
"error",
"groupCollapsed",
"Console",
"profile",
"profileEnd",
"timeStamp",
"context"
]
}
code: 140,
},
],
"no-debugger": "error",
"no-empty": "off",
"no-empty-function": "off",
"no-eval": "error",
"no-fallthrough": "error",
"no-invalid-this": "off",
"no-new-wrappers": "error",
"no-restricted-imports": [
"error",
"rxjs/Rx"
],
"no-shadow": "error",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
"no-underscore-dangle": "error",
"no-unsafe-finally": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-use-before-define": "off",
"no-var": "error",
"object-shorthand": "error",
"one-var": [
"error",
"never"
],
"prefer-arrow/prefer-arrow-functions": "error",
"prefer-const": "error",
"quote-props": [
"error",
"as-needed"
],
"quotes": "error",
"radix": "error",
"semi": "error",
"space-before-function-paren": [
"error",
'new-parens': 'error',
'no-bitwise': 'error',
'no-caller': 'error',
'no-cond-assign': 'error',
'no-console': [
'error',
{
"anonymous": "never",
"asyncArrow": "always",
"named": "never"
}
allow: [
'log',
'warn',
'dir',
'timeLog',
'assert',
'clear',
'count',
'countReset',
'group',
'groupEnd',
'table',
'dirxml',
'error',
'groupCollapsed',
'Console',
'profile',
'profileEnd',
'timeStamp',
'context',
],
},
],
"spaced-comment": [
"error",
"always",
'no-debugger': 'error',
'no-empty': 'off',
'no-empty-function': 'off',
'no-eval': 'error',
'no-fallthrough': 'error',
'no-invalid-this': 'off',
'no-new-wrappers': 'error',
'no-restricted-imports': ['error', 'rxjs/Rx'],
'no-shadow': 'error',
'no-throw-literal': 'error',
'no-trailing-spaces': 'error',
'no-undef-init': 'error',
'no-underscore-dangle': 'error',
'no-unsafe-finally': 'error',
'no-unused-expressions': 'error',
'no-unused-labels': 'error',
'no-use-before-define': 'off',
'no-var': 'error',
'object-shorthand': 'error',
'one-var': ['error', 'never'],
'prefer-arrow/prefer-arrow-functions': 'error',
'prefer-const': 'error',
'quote-props': ['error', 'as-needed'],
quotes: 'error',
radix: 'error',
semi: 'error',
'space-before-function-paren': [
'error',
{
"markers": [
"/"
]
}
anonymous: 'never',
asyncArrow: 'always',
named: 'never',
},
],
"use-isnan": "error",
"valid-typeof": "off",
"@typescript-eslint/tslint/config": [
"error",
'spaced-comment': [
'error',
'always',
{
"rules": {
"import-spacing": true,
"typedef": [
true,
"call-signature"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type",
"check-typecast"
]
}
}
]
}
markers: ['/'],
},
],
'use-isnan': 'error',
'valid-typeof': 'off',
'@typescript-eslint/tslint/config': [
'error',
{
rules: {
'import-spacing': true,
typedef: [true, 'call-signature'],
whitespace: [true, 'check-branch', 'check-decl', 'check-operator', 'check-separator', 'check-type', 'check-typecast'],
},
},
],
},
};

View file

@ -1,9 +1,9 @@
{
"bracketSpacing": true,
"tabWidth": 4,
"singleQuote": true,
"semi": true,
"useTabs": false,
"trailingComma": "es5",
"printWidth": 140
"bracketSpacing": true,
"tabWidth": 4,
"singleQuote": true,
"semi": true,
"useTabs": false,
"trailingComma": "es5",
"printWidth": 140
}

View file

@ -2,7 +2,7 @@
<img src="https://badgen.net/bundlephobia/min/ngx-pinch-zoom" />
The module provides opportunities for image zooming in, zooming out and positioning with use of gestures on a touch screen.
The module provides opportunities for image zooming in, zooming out and positioning with use of gestures on a touch screen.
Live demos and source code samples can be found on [home page](http://ivylab.space/pinch-zoom).
@ -11,11 +11,13 @@ Live demos and source code samples can be found on [home page](http://ivylab.spa
## Installation
Install the npm package.
```
npm i ngx-pinch-zoom
```
Import module:
```ts
import { PinchZoomModule } from 'ngx-pinch-zoom';
@ -25,43 +27,44 @@ import { PinchZoomModule } from 'ngx-pinch-zoom';
```
## Usage
For use, put your image inside the &lt;pinch-zoom&gt; container. Please, pay attention to the parameters of your viewport metatag. If you use Pinch Zoom, it is required to limit zooming of a web-page, by entering the following parameters: &lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"&gt;.
```html
<pinch-zoom>
<img src="path_to_image" />
<img src="path_to_image" />
</pinch-zoom>
```
## Properties
| name | type | default | description |
|------------------|-----------------|---------|---------------------------------------------|
| transition-duration | number | 200 | Defines the speed of the animation of positioning and transforming.|
| limit-zoom | number, "original image size" | "original image size" | Limit the maximum available scale. By default, the maximum scale is calculated based on the original image size. |
| minScale | number | 0 | Limit the minimum acceptable scale. With a value of 1, it is recommended to use this parameter with `limitPan` |
| auto-zoom-out | boolean | false | Automatic restoration of the original size of an image after its zooming in by two fingers.|
| double-tap | boolean | true | Zooming in and zooming out of an image, depending on its current condition, with double tap.|
| disabled | boolean | false | Disable zoom. |
| disablePan | boolean | false | Turn off panning with one finger. |
| overflow | "hidden", "visible" | "hidden" | `hidden` - the overflow is clipped, and the rest of the content will be invisible. `visible` - the overflow is not clipped. The content renders outside the element's box. |
| disableZoomControl | "disable", "never", "auto" | "auto" | Disable zoom controls. `auto` - Disable zoom controls on touch screen devices. `never` - show zoom controls on all devices. `disable` - disable zoom controls on all devices. |
| zoomControlScale | number | 1 | Zoom factor when using zoom controls. |
| backgroundColor | string | "rgba(0,0,0,0.85)" | The background color of the container. |
| limitPan | boolean | false | Stop panning when the edge of the image reaches the edge of the screen. |
| minPanScale | number | 1.0001 | Minimum zoom at which panning is enabled. |
| listeners | "auto", "mouse and touch" | "mouse and touch" | By default, subscriptions are made for mouse and touch screen events. The value `auto` means that the subscription will be only for touch events or only for mouse events, depending on the type of screen. |
| wheel | boolean | true | Scale with the mouse wheel. |
| wheelZoomFactor | number | 0.2 | Zoom factor when zoomed in with the mouse wheel. |
| autoHeight | boolean | false | Calculate the height of the container based on the `width` and `height` attributes of the image. By default, the width of the container is 100%, and the height is determined after the image information is loaded - this may cause a delay in determining the height of the container. If you want the container to initially have dimensions corresponding to the dimensions of the image, then specify the attributes `width` and `height` for the `<img>` tag. When setting the property value to `true`, a subscription to the window resize listener will be created. |
| draggableImage | boolean | false | Sets the attribute `draggable` to the `<img>` tag. |
| name | type | default | description |
| ------------------- | ----------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| transition-duration | number | 200 | Defines the speed of the animation of positioning and transforming. |
| limit-zoom | number, "original image size" | "original image size" | Limit the maximum available scale. By default, the maximum scale is calculated based on the original image size. |
| minScale | number | 0 | Limit the minimum acceptable scale. With a value of 1, it is recommended to use this parameter with `limitPan` |
| auto-zoom-out | boolean | false | Automatic restoration of the original size of an image after its zooming in by two fingers. |
| double-tap | boolean | true | Zooming in and zooming out of an image, depending on its current condition, with double tap. |
| disabled | boolean | false | Disable zoom. |
| disablePan | boolean | false | Turn off panning with one finger. |
| overflow | "hidden", "visible" | "hidden" | `hidden` - the overflow is clipped, and the rest of the content will be invisible. `visible` - the overflow is not clipped. The content renders outside the element's box. |
| disableZoomControl | "disable", "never", "auto" | "auto" | Disable zoom controls. `auto` - Disable zoom controls on touch screen devices. `never` - show zoom controls on all devices. `disable` - disable zoom controls on all devices. |
| zoomControlScale | number | 1 | Zoom factor when using zoom controls. |
| backgroundColor | string | "rgba(0,0,0,0.85)" | The background color of the container. |
| limitPan | boolean | false | Stop panning when the edge of the image reaches the edge of the screen. |
| minPanScale | number | 1.0001 | Minimum zoom at which panning is enabled. |
| listeners | "auto", "mouse and touch" | "mouse and touch" | By default, subscriptions are made for mouse and touch screen events. The value `auto` means that the subscription will be only for touch events or only for mouse events, depending on the type of screen. |
| wheel | boolean | true | Scale with the mouse wheel. |
| wheelZoomFactor | number | 0.2 | Zoom factor when zoomed in with the mouse wheel. |
| autoHeight | boolean | false | Calculate the height of the container based on the `width` and `height` attributes of the image. By default, the width of the container is 100%, and the height is determined after the image information is loaded - this may cause a delay in determining the height of the container. If you want the container to initially have dimensions corresponding to the dimensions of the image, then specify the attributes `width` and `height` for the `<img>` tag. When setting the property value to `true`, a subscription to the window resize listener will be created. |
| draggableImage | boolean | false | Sets the attribute `draggable` to the `<img>` tag. |
## Methods
| name | description |
|-------------------------|---------------------------------------------|
| toggleZoom() | Image zooming in and out, depending on its current state. |
| destroy() | Unsubscribe from mouse events and touches, as well as remove added styles from the DOM tree. |
| name | description |
| ------------ | -------------------------------------------------------------------------------------------- |
| toggleZoom() | Image zooming in and out, depending on its current state. |
| destroy() | Unsubscribe from mouse events and touches, as well as remove added styles from the DOM tree. |
See the full documentation and examples on the [home page](http://ivylab.space/pinch-zoom).

View file

@ -1,224 +1,206 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"cli": {
"analytics": false
},
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ivypinchApp": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "sass"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/ivypinchApp",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.sass"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ivypinchApp:build"
},
"configurations": {
"production": {
"browserTarget": "ivypinchApp:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "ivypinchApp:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.sass"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"cypress/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ivypinchApp:serve",
"watch": true,
"headless": false
},
"configurations": {
"production": {
"devServerTarget": "ivypinchApp:serve:production"
}
}
},
"cypress-run": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ivypinchApp:serve"
},
"configurations": {
"production": {
"devServerTarget": "ivypinchApp:serve:production"
}
}
},
"cypress-open": {
"builder": "@cypress/schematic:cypress",
"options": {
"watch": true,
"headless": false
}
}
}
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"cli": {
"analytics": false
},
"ngx-pinch-zoom": {
"projectType": "library",
"root": "projects/ngx-pinch-zoom",
"sourceRoot": "projects/ngx-pinch-zoom/src",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "projects/ngx-pinch-zoom/tsconfig.lib.json",
"project": "projects/ngx-pinch-zoom/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/ngx-pinch-zoom/tsconfig.lib.prod.json"
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ivypinchApp": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "sass"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/ivypinchApp",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.sass"],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ivypinchApp:build"
},
"configurations": {
"production": {
"browserTarget": "ivypinchApp:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "ivypinchApp:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.sass"],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "cypress/tsconfig.json"],
"exclude": ["**/node_modules/**"]
}
},
"e2e": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ivypinchApp:serve",
"watch": true,
"headless": false
},
"configurations": {
"production": {
"devServerTarget": "ivypinchApp:serve:production"
}
}
},
"cypress-run": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ivypinchApp:serve"
},
"configurations": {
"production": {
"devServerTarget": "ivypinchApp:serve:production"
}
}
},
"cypress-open": {
"builder": "@cypress/schematic:cypress",
"options": {
"watch": true,
"headless": false
}
}
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ngx-pinch-zoom/src/test.ts",
"tsConfig": "projects/ngx-pinch-zoom/tsconfig.spec.json",
"karmaConfig": "projects/ngx-pinch-zoom/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/ngx-pinch-zoom/tsconfig.lib.json",
"projects/ngx-pinch-zoom/tsconfig.spec.json",
"projects/ngx-pinch-zoom/cypress/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"cypress-run": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ngx-pinch-zoom:serve",
"configFile": "projects/ngx-pinch-zoom/cypress.json"
},
"configurations": {
"production": {
"devServerTarget": "ngx-pinch-zoom:serve:production"
"ngx-pinch-zoom": {
"projectType": "library",
"root": "projects/ngx-pinch-zoom",
"sourceRoot": "projects/ngx-pinch-zoom/src",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "projects/ngx-pinch-zoom/tsconfig.lib.json",
"project": "projects/ngx-pinch-zoom/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/ngx-pinch-zoom/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/ngx-pinch-zoom/src/test.ts",
"tsConfig": "projects/ngx-pinch-zoom/tsconfig.spec.json",
"karmaConfig": "projects/ngx-pinch-zoom/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/ngx-pinch-zoom/tsconfig.lib.json",
"projects/ngx-pinch-zoom/tsconfig.spec.json",
"projects/ngx-pinch-zoom/cypress/tsconfig.json"
],
"exclude": ["**/node_modules/**"]
}
},
"cypress-run": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ngx-pinch-zoom:serve",
"configFile": "projects/ngx-pinch-zoom/cypress.json"
},
"configurations": {
"production": {
"devServerTarget": "ngx-pinch-zoom:serve:production"
}
}
},
"cypress-open": {
"builder": "@cypress/schematic:cypress",
"options": {
"watch": true,
"headless": false,
"configFile": "projects/ngx-pinch-zoom/cypress.json"
}
},
"e2e": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ngx-pinch-zoom:serve",
"watch": true,
"headless": false
},
"configurations": {
"production": {
"devServerTarget": "ngx-pinch-zoom:serve:production"
}
}
}
}
}
},
"cypress-open": {
"builder": "@cypress/schematic:cypress",
"options": {
"watch": true,
"headless": false,
"configFile": "projects/ngx-pinch-zoom/cypress.json"
}
},
"e2e": {
"builder": "@cypress/schematic:cypress",
"options": {
"devServerTarget": "ngx-pinch-zoom:serve",
"watch": true,
"headless": false
},
"configurations": {
"production": {
"devServerTarget": "ngx-pinch-zoom:serve:production"
}
}
}
}
}
},
"defaultProject": "ivypinchApp"
}
},
"defaultProject": "ivypinchApp"
}

View file

@ -1,9 +1,9 @@
{
"integrationFolder": "cypress/integration",
"supportFile": "cypress/support/index.ts",
"videosFolder": "cypress/videos",
"screenshotsFolder": "cypress/screenshots",
"pluginsFile": "cypress/plugins/index.ts",
"fixturesFolder": "cypress/fixtures",
"baseUrl": "http://localhost:4200"
}
"integrationFolder": "cypress/integration",
"supportFile": "cypress/support/index.ts",
"videosFolder": "cypress/videos",
"screenshotsFolder": "cypress/screenshots",
"pluginsFile": "cypress/plugins/index.ts",
"fixturesFolder": "cypress/fixtures",
"baseUrl": "http://localhost:4200"
}

View file

@ -1,5 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View file

@ -1,18 +1,18 @@
Cypress.on('window:before:load', (win) => {
cy.spy(win.console, 'error');
cy.spy(win.console, 'warn');
cy.spy(win.console, 'error');
cy.spy(win.console, 'warn');
});
describe('workspace-project App', () => {
afterEach(() => {
cy.window().then((win) => {
expect(win.console.error).to.have.callCount(0);
expect(win.console.warn).to.have.callCount(0);
afterEach(() => {
cy.window().then((win) => {
expect(win.console.error).to.have.callCount(0);
expect(win.console.warn).to.have.callCount(0);
});
});
});
it('should display welcome message', () => {
cy.visit('/');
cy.get('title').should('contain.text', 'IvypinchApp');
});
it('should display welcome message', () => {
cy.visit('/');
cy.get('title').should('contain.text', 'IvypinchApp');
});
});

View file

@ -1,3 +1,3 @@
// Plugins enable you to tap into, modify, or extend the internal behavior of Cypress
// For more info, visit https://on.cypress.io/plugins-api
module.exports = (on, config) => {}
module.exports = (on, config) => {};

View file

@ -1,8 +1,8 @@
{
"extends": "../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"sourceMap": false,
"types": ["cypress", "node"]
}
"extends": "../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"sourceMap": false,
"types": ["cypress", "node"]
}
}

View file

@ -2,43 +2,40 @@
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/ivypinchApp'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/ivypinchApp'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }],
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
});
};

View file

@ -12,302 +12,257 @@ https://github.com/typescript-eslint/tslint-to-eslint-config/blob/master/docs/FA
Happy linting! 💖
*/
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
env: {
browser: true,
es6: true,
node: true,
},
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
extends: ['plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended-requiring-type-checking'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
"plugins": [
"eslint-plugin-import",
"eslint-plugin-jsdoc",
"@angular-eslint/eslint-plugin",
"@angular-eslint/eslint-plugin-template",
"eslint-plugin-prefer-arrow",
"@typescript-eslint",
"@typescript-eslint/tslint"
plugins: [
'eslint-plugin-import',
'eslint-plugin-jsdoc',
'@angular-eslint/eslint-plugin',
'@angular-eslint/eslint-plugin-template',
'eslint-plugin-prefer-arrow',
'@typescript-eslint',
'@typescript-eslint/tslint',
],
"rules": {
"@angular-eslint/component-class-suffix": "error",
"@angular-eslint/component-selector": [
"error",
rules: {
'@angular-eslint/component-class-suffix': 'error',
'@angular-eslint/component-selector': [
'error',
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
type: 'element',
prefix: 'app',
style: 'kebab-case',
},
],
"@angular-eslint/contextual-lifecycle": "error",
"@angular-eslint/directive-class-suffix": "error",
"@angular-eslint/directive-selector": [
"error",
'@angular-eslint/contextual-lifecycle': 'error',
'@angular-eslint/directive-class-suffix': 'error',
'@angular-eslint/directive-selector': [
'error',
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
type: 'attribute',
prefix: 'app',
style: 'camelCase',
},
],
"@angular-eslint/no-conflicting-lifecycle": "error",
"@angular-eslint/no-host-metadata-property": "error",
"@angular-eslint/no-input-rename": "error",
"@angular-eslint/no-inputs-metadata-property": "error",
"@angular-eslint/no-output-native": "error",
"@angular-eslint/no-output-on-prefix": "error",
"@angular-eslint/no-output-rename": "error",
"@angular-eslint/no-outputs-metadata-property": "error",
"@angular-eslint/template/banana-in-box": "error",
"@angular-eslint/template/eqeqeq": "error",
"@angular-eslint/template/no-negated-async": "error",
"@angular-eslint/use-lifecycle-interface": "error",
"@angular-eslint/use-pipe-transform-interface": "error",
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "off",
"@typescript-eslint/ban-types": [
"error",
'@angular-eslint/no-conflicting-lifecycle': 'error',
'@angular-eslint/no-host-metadata-property': 'error',
'@angular-eslint/no-input-rename': 'error',
'@angular-eslint/no-inputs-metadata-property': 'error',
'@angular-eslint/no-output-native': 'error',
'@angular-eslint/no-output-on-prefix': 'error',
'@angular-eslint/no-output-rename': 'error',
'@angular-eslint/no-outputs-metadata-property': 'error',
'@angular-eslint/template/banana-in-box': 'error',
'@angular-eslint/template/eqeqeq': 'error',
'@angular-eslint/template/no-negated-async': 'error',
'@angular-eslint/use-lifecycle-interface': 'error',
'@angular-eslint/use-pipe-transform-interface': 'error',
'@typescript-eslint/adjacent-overload-signatures': 'error',
'@typescript-eslint/array-type': 'off',
'@typescript-eslint/ban-types': [
'error',
{
"types": {
"Object": {
"message": "Avoid using the `Object` type. Did you mean `object`?"
types: {
Object: {
message: 'Avoid using the `Object` type. Did you mean `object`?',
},
"Function": {
"message": "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."
Function: {
message: 'Avoid using the `Function` type. Prefer a specific function type, like `() => void`.',
},
"Boolean": {
"message": "Avoid using the `Boolean` type. Did you mean `boolean`?"
Boolean: {
message: 'Avoid using the `Boolean` type. Did you mean `boolean`?',
},
"Number": {
"message": "Avoid using the `Number` type. Did you mean `number`?"
Number: {
message: 'Avoid using the `Number` type. Did you mean `number`?',
},
"String": {
"message": "Avoid using the `String` type. Did you mean `string`?"
String: {
message: 'Avoid using the `String` type. Did you mean `string`?',
},
"Symbol": {
"message": "Avoid using the `Symbol` type. Did you mean `symbol`?"
}
}
}
Symbol: {
message: 'Avoid using the `Symbol` type. Did you mean `symbol`?',
},
},
},
],
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/dot-notation": "error",
"@typescript-eslint/indent": [
"error",
'@typescript-eslint/consistent-type-assertions': 'error',
'@typescript-eslint/dot-notation': 'error',
'@typescript-eslint/indent': [
'error',
4,
{
"FunctionDeclaration": {
"parameters": "first"
FunctionDeclaration: {
parameters: 'first',
},
"FunctionExpression": {
"parameters": "first"
}
}
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "semi",
"requireLast": true
FunctionExpression: {
parameters: 'first',
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
},
],
"@typescript-eslint/member-ordering": "error",
"@typescript-eslint/naming-convention": "error",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-inferrable-types": [
"error",
'@typescript-eslint/member-delimiter-style': [
'error',
{
"ignoreParameters": true
}
multiline: {
delimiter: 'semi',
requireLast: true,
},
singleline: {
delimiter: 'semi',
requireLast: false,
},
},
],
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-shadow": [
"error",
'@typescript-eslint/member-ordering': 'error',
'@typescript-eslint/naming-convention': 'error',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-empty-interface': 'error',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-inferrable-types': [
'error',
{
"hoist": "all"
}
ignoreParameters: true,
},
],
"@typescript-eslint/no-unused-expressions": "error",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/quotes": [
"error",
"single"
],
"@typescript-eslint/semi": [
"error",
"always"
],
"@typescript-eslint/triple-slash-reference": [
"error",
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-parameter-properties': 'off',
'@typescript-eslint/no-shadow': [
'error',
{
"path": "always",
"types": "prefer-import",
"lib": "always"
}
hoist: 'all',
},
],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unified-signatures": "error",
"arrow-body-style": "error",
"complexity": "off",
"constructor-super": "error",
"curly": "error",
"dot-notation": "error",
"eol-last": "error",
"eqeqeq": [
"error",
"smart"
],
"guard-for-in": "error",
"id-denylist": [
"error",
"any",
"Number",
"number",
"String",
"string",
"Boolean",
"boolean",
"Undefined",
"undefined"
],
"id-match": "error",
"import/no-deprecated": "warn",
"indent": "error",
"jsdoc/check-alignment": "error",
"jsdoc/check-indentation": "error",
"jsdoc/newline-after-description": "error",
"jsdoc/no-types": "error",
"max-classes-per-file": "off",
"max-len": [
"error",
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-namespace-keyword': 'error',
'@typescript-eslint/quotes': ['error', 'single'],
'@typescript-eslint/semi': ['error', 'always'],
'@typescript-eslint/triple-slash-reference': [
'error',
{
"code": 140
}
path: 'always',
types: 'prefer-import',
lib: 'always',
},
],
"new-parens": "error",
"no-bitwise": "error",
"no-caller": "error",
"no-cond-assign": "error",
"no-console": [
"error",
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/unified-signatures': 'error',
'arrow-body-style': 'error',
complexity: 'off',
'constructor-super': 'error',
curly: 'error',
'dot-notation': 'error',
'eol-last': 'error',
eqeqeq: ['error', 'smart'],
'guard-for-in': 'error',
'id-denylist': ['error', 'any', 'Number', 'number', 'String', 'string', 'Boolean', 'boolean', 'Undefined', 'undefined'],
'id-match': 'error',
'import/no-deprecated': 'warn',
indent: 'error',
'jsdoc/check-alignment': 'error',
'jsdoc/check-indentation': 'error',
'jsdoc/newline-after-description': 'error',
'jsdoc/no-types': 'error',
'max-classes-per-file': 'off',
'max-len': [
'error',
{
"allow": [
"log",
"warn",
"dir",
"timeLog",
"assert",
"clear",
"count",
"countReset",
"group",
"groupEnd",
"table",
"dirxml",
"error",
"groupCollapsed",
"Console",
"profile",
"profileEnd",
"timeStamp",
"context"
]
}
code: 140,
},
],
"no-debugger": "error",
"no-empty": "off",
"no-empty-function": "off",
"no-eval": "error",
"no-fallthrough": "error",
"no-invalid-this": "off",
"no-new-wrappers": "error",
"no-restricted-imports": [
"error",
"rxjs/Rx"
],
"no-shadow": "error",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
"no-underscore-dangle": "error",
"no-unsafe-finally": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-use-before-define": "off",
"no-var": "error",
"object-shorthand": "error",
"one-var": [
"error",
"never"
],
"prefer-arrow/prefer-arrow-functions": "error",
"prefer-const": "error",
"quote-props": [
"error",
"as-needed"
],
"quotes": "error",
"radix": "error",
"semi": "error",
"space-before-function-paren": [
"error",
'new-parens': 'error',
'no-bitwise': 'error',
'no-caller': 'error',
'no-cond-assign': 'error',
'no-console': [
'error',
{
"anonymous": "never",
"asyncArrow": "always",
"named": "never"
}
allow: [
'log',
'warn',
'dir',
'timeLog',
'assert',
'clear',
'count',
'countReset',
'group',
'groupEnd',
'table',
'dirxml',
'error',
'groupCollapsed',
'Console',
'profile',
'profileEnd',
'timeStamp',
'context',
],
},
],
"spaced-comment": [
"error",
"always",
'no-debugger': 'error',
'no-empty': 'off',
'no-empty-function': 'off',
'no-eval': 'error',
'no-fallthrough': 'error',
'no-invalid-this': 'off',
'no-new-wrappers': 'error',
'no-restricted-imports': ['error', 'rxjs/Rx'],
'no-shadow': 'error',
'no-throw-literal': 'error',
'no-trailing-spaces': 'error',
'no-undef-init': 'error',
'no-underscore-dangle': 'error',
'no-unsafe-finally': 'error',
'no-unused-expressions': 'error',
'no-unused-labels': 'error',
'no-use-before-define': 'off',
'no-var': 'error',
'object-shorthand': 'error',
'one-var': ['error', 'never'],
'prefer-arrow/prefer-arrow-functions': 'error',
'prefer-const': 'error',
'quote-props': ['error', 'as-needed'],
quotes: 'error',
radix: 'error',
semi: 'error',
'space-before-function-paren': [
'error',
{
"markers": [
"/"
]
}
anonymous: 'never',
asyncArrow: 'always',
named: 'never',
},
],
"use-isnan": "error",
"valid-typeof": "off",
"@typescript-eslint/tslint/config": [
"error",
'spaced-comment': [
'error',
'always',
{
"rules": {
"import-spacing": true,
"typedef": [
true,
"call-signature"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type",
"check-typecast"
]
}
}
]
}
markers: ['/'],
},
],
'use-isnan': 'error',
'valid-typeof': 'off',
'@typescript-eslint/tslint/config': [
'error',
{
rules: {
'import-spacing': true,
typedef: [true, 'call-signature'],
whitespace: [true, 'check-branch', 'check-decl', 'check-operator', 'check-separator', 'check-type', 'check-typecast'],
},
},
],
},
};

View file

@ -2,7 +2,7 @@
<img src="https://badgen.net/bundlephobia/min/ngx-pinch-zoom" />
The module provides opportunities for image zooming in, zooming out and positioning with use of gestures on a touch screen.
The module provides opportunities for image zooming in, zooming out and positioning with use of gestures on a touch screen.
Live demos and source code samples can be found on [home page](http://ivylab.space/pinch-zoom).
@ -11,11 +11,13 @@ Live demos and source code samples can be found on [home page](http://ivylab.spa
## Installation
Install the npm package.
```
npm i ngx-pinch-zoom
```
Import module:
```ts
import { PinchZoomModule } from 'ngx-pinch-zoom';
@ -25,43 +27,44 @@ import { PinchZoomModule } from 'ngx-pinch-zoom';
```
## Usage
For use, put your image inside the &lt;pinch-zoom&gt; container. Please, pay attention to the parameters of your viewport metatag. If you use Pinch Zoom, it is required to limit zooming of a web-page, by entering the following parameters: &lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"&gt;.
```html
<pinch-zoom>
<img src="path_to_image" />
<img src="path_to_image" />
</pinch-zoom>
```
## Properties
| name | type | default | description |
|------------------|-----------------|---------|---------------------------------------------|
| transition-duration | number | 200 | Defines the speed of the animation of positioning and transforming.|
| limit-zoom | number, "original image size" | "original image size" | Limit the maximum available scale. By default, the maximum scale is calculated based on the original image size. |
| minScale | number | 0 | Limit the minimum acceptable scale. With a value of 1, it is recommended to use this parameter with `limitPan` |
| auto-zoom-out | boolean | false | Automatic restoration of the original size of an image after its zooming in by two fingers.|
| double-tap | boolean | true | Zooming in and zooming out of an image, depending on its current condition, with double tap.|
| disabled | boolean | false | Disable zoom. |
| disablePan | boolean | false | Turn off panning with one finger. |
| overflow | "hidden", "visible" | "hidden" | `hidden` - the overflow is clipped, and the rest of the content will be invisible. `visible` - the overflow is not clipped. The content renders outside the element's box. |
| disableZoomControl | "disable", "never", "auto" | "auto" | Disable zoom controls. `auto` - Disable zoom controls on touch screen devices. `never` - show zoom controls on all devices. `disable` - disable zoom controls on all devices. |
| zoomControlScale | number | 1 | Zoom factor when using zoom controls. |
| backgroundColor | string | "rgba(0,0,0,0.85)" | The background color of the container. |
| limitPan | boolean | false | Stop panning when the edge of the image reaches the edge of the screen. |
| minPanScale | number | 1.0001 | Minimum zoom at which panning is enabled. |
| listeners | "auto", "mouse and touch" | "mouse and touch" | By default, subscriptions are made for mouse and touch screen events. The value `auto` means that the subscription will be only for touch events or only for mouse events, depending on the type of screen. |
| wheel | boolean | true | Scale with the mouse wheel. |
| wheelZoomFactor | number | 0.2 | Zoom factor when zoomed in with the mouse wheel. |
| autoHeight | boolean | false | Calculate the height of the container based on the `width` and `height` attributes of the image. By default, the width of the container is 100%, and the height is determined after the image information is loaded - this may cause a delay in determining the height of the container. If you want the container to initially have dimensions corresponding to the dimensions of the image, then specify the attributes `width` and `height` for the `<img>` tag. When setting the property value to `true`, a subscription to the window resize listener will be created. |
| draggableImage | boolean | false | Sets the attribute `draggable` to the `<img>` tag. |
| name | type | default | description |
| ------------------- | ----------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| transition-duration | number | 200 | Defines the speed of the animation of positioning and transforming. |
| limit-zoom | number, "original image size" | "original image size" | Limit the maximum available scale. By default, the maximum scale is calculated based on the original image size. |
| minScale | number | 0 | Limit the minimum acceptable scale. With a value of 1, it is recommended to use this parameter with `limitPan` |
| auto-zoom-out | boolean | false | Automatic restoration of the original size of an image after its zooming in by two fingers. |
| double-tap | boolean | true | Zooming in and zooming out of an image, depending on its current condition, with double tap. |
| disabled | boolean | false | Disable zoom. |
| disablePan | boolean | false | Turn off panning with one finger. |
| overflow | "hidden", "visible" | "hidden" | `hidden` - the overflow is clipped, and the rest of the content will be invisible. `visible` - the overflow is not clipped. The content renders outside the element's box. |
| disableZoomControl | "disable", "never", "auto" | "auto" | Disable zoom controls. `auto` - Disable zoom controls on touch screen devices. `never` - show zoom controls on all devices. `disable` - disable zoom controls on all devices. |
| zoomControlScale | number | 1 | Zoom factor when using zoom controls. |
| backgroundColor | string | "rgba(0,0,0,0.85)" | The background color of the container. |
| limitPan | boolean | false | Stop panning when the edge of the image reaches the edge of the screen. |
| minPanScale | number | 1.0001 | Minimum zoom at which panning is enabled. |
| listeners | "auto", "mouse and touch" | "mouse and touch" | By default, subscriptions are made for mouse and touch screen events. The value `auto` means that the subscription will be only for touch events or only for mouse events, depending on the type of screen. |
| wheel | boolean | true | Scale with the mouse wheel. |
| wheelZoomFactor | number | 0.2 | Zoom factor when zoomed in with the mouse wheel. |
| autoHeight | boolean | false | Calculate the height of the container based on the `width` and `height` attributes of the image. By default, the width of the container is 100%, and the height is determined after the image information is loaded - this may cause a delay in determining the height of the container. If you want the container to initially have dimensions corresponding to the dimensions of the image, then specify the attributes `width` and `height` for the `<img>` tag. When setting the property value to `true`, a subscription to the window resize listener will be created. |
| draggableImage | boolean | false | Sets the attribute `draggable` to the `<img>` tag. |
## Methods
| name | description |
|-------------------------|---------------------------------------------|
| toggleZoom() | Image zooming in and out, depending on its current state. |
| destroy() | Unsubscribe from mouse events and touches, as well as remove added styles from the DOM tree. |
| name | description |
| ------------ | -------------------------------------------------------------------------------------------- |
| toggleZoom() | Image zooming in and out, depending on its current state. |
| destroy() | Unsubscribe from mouse events and touches, as well as remove added styles from the DOM tree. |
See the full documentation and examples on the [home page](http://ivylab.space/pinch-zoom).

View file

@ -1,9 +1,9 @@
{
"integrationFolder": "projects/ngx-pinch-zoom/cypress/integration",
"supportFile": "projects/ngx-pinch-zoom/cypress/support/index.ts",
"videosFolder": "projects/ngx-pinch-zoom/cypress/videos",
"screenshotsFolder": "projects/ngx-pinch-zoom/cypress/screenshots",
"pluginsFile": "projects/ngx-pinch-zoom/cypress/plugins/index.ts",
"fixturesFolder": "projects/ngx-pinch-zoom/cypress/fixtures",
"baseUrl": "http://localhost:4200"
}
"integrationFolder": "projects/ngx-pinch-zoom/cypress/integration",
"supportFile": "projects/ngx-pinch-zoom/cypress/support/index.ts",
"videosFolder": "projects/ngx-pinch-zoom/cypress/videos",
"screenshotsFolder": "projects/ngx-pinch-zoom/cypress/screenshots",
"pluginsFile": "projects/ngx-pinch-zoom/cypress/plugins/index.ts",
"fixturesFolder": "projects/ngx-pinch-zoom/cypress/fixtures",
"baseUrl": "http://localhost:4200"
}

View file

@ -1,7 +1,7 @@
describe('My First Test', () => {
it('Visits the initial project page', () => {
cy.visit('/')
cy.contains('Welcome')
cy.contains('sandbox app is running!')
})
})
it('Visits the initial project page', () => {
cy.visit('/');
cy.contains('Welcome');
cy.contains('sandbox app is running!');
});
});

View file

@ -1,3 +1,3 @@
// Plugins enable you to tap into, modify, or extend the internal behavior of Cypress
// For more info, visit https://on.cypress.io/plugins-api
module.exports = (on, config) => {}
module.exports = (on, config) => {};

View file

@ -1,8 +1,8 @@
{
"extends": "../../../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"sourceMap": false,
"types": ["cypress", "node"]
}
"extends": "../../../tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"sourceMap": false,
"types": ["cypress", "node"]
}
}

View file

@ -2,43 +2,40 @@
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/ngx-pinch-zoom'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/ngx-pinch-zoom'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }],
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
});
};

View file

@ -1,7 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/ngx-pinch-zoom",
"lib": {
"entryFile": "src/public-api.ts"
}
}
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/ngx-pinch-zoom",
"lib": {
"entryFile": "src/public-api.ts"
}
}

View file

@ -1,23 +1,23 @@
export interface Properties {
element ? : string;
doubleTap ? : boolean;
doubleTapScale ? : number;
zoomControlScale ? : number;
transitionDuration ? : number;
autoZoomOut ? : boolean;
limitZoom ? : number | string | "original image size";
disablePan ? : boolean;
limitPan ? : boolean;
minPanScale ? : number;
minScale ? : number;
eventHandler ? : any;
listeners ? : string | "auto" | "mouse and touch";
wheel ? : boolean;
fullImage ? : {
path: string,
minScale?: number
element?: string;
doubleTap?: boolean;
doubleTapScale?: number;
zoomControlScale?: number;
transitionDuration?: number;
autoZoomOut?: boolean;
limitZoom?: number | string | 'original image size';
disablePan?: boolean;
limitPan?: boolean;
minPanScale?: number;
minScale?: number;
eventHandler?: any;
listeners?: string | 'auto' | 'mouse and touch';
wheel?: boolean;
fullImage?: {
path: string;
minScale?: number;
};
autoHeight ? : boolean;
wheelZoomFactor ? : number;
draggableImage ? : boolean;
}
autoHeight?: boolean;
wheelZoomFactor?: number;
draggableImage?: boolean;
}

View file

@ -1,6 +1,6 @@
import {Touches} from './touches';
import {Properties} from './interfaces';
import {defaultProperties} from './properties';
import { Touches } from './touches';
import { Properties } from './interfaces';
import { defaultProperties } from './properties';
type PropertyName = keyof Properties;
@ -34,7 +34,7 @@ export class IvyPinch {
// Minimum scale at which panning works
get minPanScale() {
return this.getPropertiesValue("minPanScale");
return this.getPropertiesValue('minPanScale');
}
get fullImage() {
@ -58,13 +58,12 @@ export class IvyPinch {
listeners: properties.listeners,
resize: properties.autoHeight,
mouseListeners: {
"mousedown": "handleMousedown",
"mouseup": "handleMouseup",
"wheel": "handleWheel"
}
mousedown: 'handleMousedown',
mouseup: 'handleMouseup',
wheel: 'handleWheel',
},
});
/* Init */
this.setBasicStyles();
@ -93,25 +92,22 @@ export class IvyPinch {
}
}
/* Touchstart */
handleTouchstart = (event: any) => {
this.touches.addEventListeners("mousemove", "handleMousemove");
this.touches.addEventListeners('mousemove', 'handleMousemove');
this.getElementPosition();
if (this.eventType === undefined) {
this.getTouchstartPosition(event);
}
}
};
/* Touchend */
handleTouchend = (event: any) => {
/* touchend */
if (event.type === "touchend") {
if (event.type === 'touchend') {
this.i = 0;
this.draggingMode = false;
const touches = event.touches;
@ -127,18 +123,17 @@ export class IvyPinch {
}
// Align image
if (this.eventType === 'pinch' ||
this.eventType === 'pan' && this.scale > this.minPanScale) {
if (this.eventType === 'pinch' || (this.eventType === 'pan' && this.scale > this.minPanScale)) {
this.alignImage();
}
// Update initial values
if (this.eventType === 'pinch' ||
if (
this.eventType === 'pinch' ||
this.eventType === 'pan' ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
this.eventType === 'vertical-swipe'
) {
this.updateInitialValues();
}
@ -150,15 +145,14 @@ export class IvyPinch {
}
/* mouseup */
if (event.type === "mouseup") {
if (event.type === 'mouseup') {
this.draggingMode = false;
this.updateInitialValues();
this.eventType = undefined;
}
this.touches.removeEventListeners("mousemove", "handleMousemove");
}
this.touches.removeEventListeners('mousemove', 'handleMousemove');
};
/*
* Handlers
@ -170,10 +164,7 @@ export class IvyPinch {
}
event.preventDefault();
const {
clientX,
clientY
} = this.getClientPosition(event);
const { clientX, clientY } = this.getClientPosition(event);
if (!this.eventType) {
this.startX = clientX - this.elementPosition.left;
@ -190,17 +181,17 @@ export class IvyPinch {
}
/* mousemove */
if (event.type === "mousemove" && this.scale > this.minPanScale) {
if (event.type === 'mousemove' && this.scale > this.minPanScale) {
this.centeringImage();
}
this.transformElement(0);
}
};
handleDoubleTap = (event: any) => {
this.toggleZoom(event);
return;
}
};
handlePinch = (event: any) => {
event.preventDefault();
@ -216,15 +207,15 @@ export class IvyPinch {
const moveTop0 = this.moveTop(event, 0);
const moveTop1 = this.moveTop(event, 1);
this.moveXC = ((moveLeft0 + moveLeft1) / 2) - this.initialMoveX;
this.moveYC = ((moveTop0 + moveTop1) / 2) - this.initialMoveY;
this.moveXC = (moveLeft0 + moveLeft1) / 2 - this.initialMoveX;
this.moveYC = (moveTop0 + moveTop1) / 2 - this.initialMoveY;
}
this.eventType = 'pinch';
this.distance = this.getDistance(touches);
this.scale = this.initialScale * (this.distance / this.initialDistance);
this.moveX = this.initialMoveX - (((this.distance / this.initialDistance) * this.moveXC) - this.moveXC);
this.moveY = this.initialMoveY - (((this.distance / this.initialDistance) * this.moveYC) - this.moveYC);
this.moveX = this.initialMoveX - ((this.distance / this.initialDistance) * this.moveXC - this.moveXC);
this.moveY = this.initialMoveY - ((this.distance / this.initialDistance) * this.moveYC - this.moveYC);
this.handleLimitZoom();
@ -235,18 +226,17 @@ export class IvyPinch {
this.transformElement(0);
}
}
};
handleWheel = (event: any) => {
event.preventDefault();
let wheelZoomFactor = this.properties.wheelZoomFactor || 0;
let zoomFactor = event.deltaY < 0 ? (wheelZoomFactor) : (- wheelZoomFactor);
let zoomFactor = event.deltaY < 0 ? wheelZoomFactor : -wheelZoomFactor;
let newScale = this.initialScale + zoomFactor;
/* Round value */
if (newScale < (1 + wheelZoomFactor)) {
if (newScale < 1 + wheelZoomFactor) {
newScale = 1;
} else if (newScale < this.maxScale && newScale > this.maxScale - wheelZoomFactor) {
newScale = this.maxScale;
@ -264,18 +254,18 @@ export class IvyPinch {
this.scale = newScale;
/* Get cursor position over image */
let xCenter = (event.clientX - this.elementPosition.left) - this.initialMoveX;
let yCenter = (event.clientY - this.elementPosition.top) - this.initialMoveY;
let xCenter = event.clientX - this.elementPosition.left - this.initialMoveX;
let yCenter = event.clientY - this.elementPosition.top - this.initialMoveY;
this.setZoom({
scale: newScale,
center: [xCenter, yCenter]
center: [xCenter, yCenter],
});
}
};
handleResize = (_event: any) => {
this.setAutoHeight();
}
};
handleLimitZoom() {
const limitZoom = this.maxScale;
@ -300,8 +290,8 @@ export class IvyPinch {
const newImageWidth = imageWidth * this.scale;
const newImageHeight = imageHeight * this.scale;
this.moveX = -Math.abs((moveXRatio * (newImageWidth - imageWidth)));
this.moveY = -Math.abs((-moveYRatio * (newImageHeight - imageHeight)));
this.moveX = -Math.abs(moveXRatio * (newImageWidth - imageWidth));
this.moveY = -Math.abs(-moveYRatio * (newImageHeight - imageHeight));
}
}
@ -315,7 +305,6 @@ export class IvyPinch {
return clientY - this.elementPosition.top;
}
/*
* Detection
*/
@ -358,7 +347,7 @@ export class IvyPinch {
if (this.moveY > imgOffsetTop) {
this.moveY = imgOffsetTop;
} else if ((scaledImgHeight + Math.abs(imgOffsetTop) - parentHeight) + this.moveY < 0) {
} else if (scaledImgHeight + Math.abs(imgOffsetTop) - parentHeight + this.moveY < 0) {
this.moveY = -(scaledImgHeight + Math.abs(imgOffsetTop) - parentHeight);
}
}
@ -377,7 +366,7 @@ export class IvyPinch {
if (this.moveX > imgOffsetLeft) {
this.moveX = imgOffsetLeft;
} else if ((scaledImgWidth + Math.abs(imgOffsetLeft) - parentWidth) + this.moveX < 0) {
} else if (scaledImgWidth + Math.abs(imgOffsetLeft) - parentWidth + this.moveX < 0) {
this.moveX = -(imgWidth * this.scale + Math.abs(imgOffsetLeft) - parentWidth);
}
}
@ -435,12 +424,12 @@ export class IvyPinch {
return;
}
const imgNaturalWidth = imgElement[0].getAttribute("width");
const imgNaturalHeight = imgElement[0].getAttribute("height");
const imgNaturalWidth = imgElement[0].getAttribute('width');
const imgNaturalHeight = imgElement[0].getAttribute('height');
const sizeRatio = imgNaturalWidth / imgNaturalHeight;
const parentWidth = this.parentElement.offsetWidth;
imgElement[0].style.maxHeight = parentWidth / sizeRatio + "px";
imgElement[0].style.maxHeight = parentWidth / sizeRatio + 'px';
}
removeImageSize() {
@ -457,10 +446,7 @@ export class IvyPinch {
}
getTouchstartPosition(event: any) {
const {
clientX,
clientY
} = this.getClientPosition(event);
const { clientX, clientY } = this.getClientPosition(event);
this.startX = clientX - this.elementPosition.left;
this.startY = clientY - this.elementPosition.top;
@ -470,18 +456,18 @@ export class IvyPinch {
let clientX;
let clientY;
if (event.type === "touchstart" || event.type === "touchmove") {
if (event.type === 'touchstart' || event.type === 'touchmove') {
clientX = event.touches[index].clientX;
clientY = event.touches[index].clientY;
}
if (event.type === "mousedown" || event.type === "mousemove") {
if (event.type === 'mousedown' || event.type === 'mousemove') {
clientX = event.clientX;
clientY = event.clientY;
}
return {
clientX,
clientY
clientY,
};
}
@ -514,14 +500,15 @@ export class IvyPinch {
}
transformElement(duration: any) {
this.element.style.transition = "all " + duration + "ms";
this.element.style.transform = "matrix(" + Number(this.scale) + ", 0, 0, " + Number(this.scale) + ", " + Number(this.moveX) + ", " + Number(this.moveY) + ")";
this.element.style.transition = 'all ' + duration + 'ms';
this.element.style.transform =
'matrix(' + Number(this.scale) + ', 0, 0, ' + Number(this.scale) + ', ' + Number(this.moveX) + ', ' + Number(this.moveY) + ')';
}
isTouchScreen() {
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
if (('ontouchstart' in window)) {
if ('ontouchstart' in window) {
return true;
}
@ -544,12 +531,10 @@ export class IvyPinch {
const imgWidth = this.getImageWidth();
if (this.scale > 1) {
return imgHeight * this.scale > this.parentElement.offsetHeight ||
imgWidth * this.scale > this.parentElement.offsetWidth;
return imgHeight * this.scale > this.parentElement.offsetHeight || imgWidth * this.scale > this.parentElement.offsetWidth;
}
if (this.scale === 1) {
return imgHeight > this.parentElement.offsetHeight ||
imgWidth > this.parentElement.offsetWidth;
return imgHeight > this.parentElement.offsetHeight || imgWidth > this.parentElement.offsetWidth;
}
return undefined;
@ -558,8 +543,7 @@ export class IvyPinch {
detectLimitZoom() {
this.maxScale = this.defaultMaxScale;
if (this.properties.limitZoom === "original image size" &&
this.elementTarget === "IMG") {
if (this.properties.limitZoom === 'original image size' && this.elementTarget === 'IMG') {
// We are waiting for the element with the image to be available
this.pollLimitZoomForOriginalImage();
}
@ -576,8 +560,8 @@ export class IvyPinch {
}
getMaxScaleForOriginalImage() {
let maxScale!:number;
let img = this.element.getElementsByTagName("img")[0];
let maxScale!: number;
let img = this.element.getElementsByTagName('img')[0];
if (img.naturalWidth && img.offsetWidth) {
maxScale = img.naturalWidth / img.offsetWidth;
@ -603,13 +587,15 @@ export class IvyPinch {
const changedTouches = event.changedTouches;
this.scale = this.initialScale * this.properties.doubleTapScale;
this.moveX = this.initialMoveX - (changedTouches[0].clientX - this.elementPosition.left) * (this.properties.doubleTapScale - 1);
this.moveY = this.initialMoveY - (changedTouches[0].clientY - this.elementPosition.top) * (this.properties.doubleTapScale - 1);
this.moveX =
this.initialMoveX - (changedTouches[0].clientX - this.elementPosition.left) * (this.properties.doubleTapScale - 1);
this.moveY =
this.initialMoveY - (changedTouches[0].clientY - this.elementPosition.top) * (this.properties.doubleTapScale - 1);
} else {
let zoomControlScale = this.properties.zoomControlScale || 0;
this.scale = this.initialScale * (zoomControlScale + 1);
this.moveX = this.initialMoveX - this.element.offsetWidth * (this.scale - 1) / 2;
this.moveY = this.initialMoveY - this.element.offsetHeight * (this.scale - 1) / 2;
this.moveX = this.initialMoveX - (this.element.offsetWidth * (this.scale - 1)) / 2;
this.moveY = this.initialMoveY - (this.element.offsetHeight * (this.scale - 1)) / 2;
}
this.centeringImage();
@ -620,10 +606,7 @@ export class IvyPinch {
}
}
setZoom(properties: {
scale: number,
center?: number[]
}) {
setZoom(properties: { scale: number; center?: number[] }) {
this.scale = properties.scale;
let xCenter;
@ -640,8 +623,8 @@ export class IvyPinch {
yCenter = visibleAreaHeight / 2 - this.initialMoveY;
}
this.moveX = this.initialMoveX - ((scalingPercent * xCenter) - xCenter);
this.moveY = this.initialMoveY - ((scalingPercent * yCenter) - yCenter);
this.moveX = this.initialMoveX - (scalingPercent * xCenter - xCenter);
this.moveY = this.initialMoveY - (scalingPercent * yCenter - yCenter);
this.centeringImage();
this.updateInitialValues();
@ -662,11 +645,11 @@ export class IvyPinch {
this.touches.destroy();
}
getPropertiesValue(propertyName:PropertyName) {
getPropertiesValue(propertyName: PropertyName) {
if (this.properties && this.properties[propertyName]) {
return this.properties[propertyName]
return this.properties[propertyName];
} else {
return defaultProperties[propertyName];
}
}
}
}

View file

@ -1,9 +1,11 @@
<div class="pinch-zoom-content" [class.pz-dragging]="isDragging">
<ng-content></ng-content>
<ng-content></ng-content>
</div>
<!-- Control: one button -->
<div class="pz-zoom-button pz-zoom-control-position-bottom"
[class.pz-zoom-button-out]="isZoomedIn"
*ngIf="isControl()"
(click)="toggleZoom()"></div>
<div
class="pz-zoom-button pz-zoom-control-position-bottom"
[class.pz-zoom-button-out]="isZoomedIn"
*ngIf="isControl()"
(click)="toggleZoom()"
></div>

View file

@ -3,23 +3,11 @@ import { CommonModule } from '@angular/common';
import { PinchZoomComponent } from './pinch-zoom.component';
@NgModule({
declarations: [
PinchZoomComponent
],
imports: [
CommonModule
],
exports: [
PinchZoomComponent
],
providers: [
],
bootstrap: [
],
entryComponents: [
PinchZoomComponent
]
declarations: [PinchZoomComponent],
imports: [CommonModule],
exports: [PinchZoomComponent],
providers: [],
bootstrap: [],
entryComponents: [PinchZoomComponent],
})
export class PinchZoomModule { }
export class PinchZoomModule {}

View file

@ -1,29 +1,29 @@
import {Properties} from './interfaces';
import { Properties } from './interfaces';
export const defaultProperties:Properties = {
export const defaultProperties: Properties = {
transitionDuration: 200,
doubleTap: true,
doubleTapScale: 2,
limitZoom: "original image size",
limitZoom: 'original image size',
autoZoomOut: false,
zoomControlScale: 1,
minPanScale: 1.0001,
minScale: 0,
listeners: "mouse and touch",
listeners: 'mouse and touch',
wheel: true,
wheelZoomFactor: 0.2,
draggableImage: false
}
draggableImage: false,
};
export const backwardCompatibilityProperties:any = {
"transition-duration": "transitionDuration",
"transitionDurationBackwardCompatibility": "transitionDuration",
"double-tap": "doubleTap",
"doubleTapBackwardCompatibility": "doubleTap",
"double-tap-scale": "doubleTapScale",
"doubleTapScaleBackwardCompatibility": "doubleTapScale",
"auto-zoom-out": "autoZoomOut",
"autoZoomOutBackwardCompatibility": "autoZoomOut",
"limit-zoom": "limitZoom",
"limitZoomBackwardCompatibility": "limitZoom"
}
export const backwardCompatibilityProperties: any = {
'transition-duration': 'transitionDuration',
transitionDurationBackwardCompatibility: 'transitionDuration',
'double-tap': 'doubleTap',
doubleTapBackwardCompatibility: 'doubleTap',
'double-tap-scale': 'doubleTapScale',
doubleTapScaleBackwardCompatibility: 'doubleTapScale',
'auto-zoom-out': 'autoZoomOut',
autoZoomOutBackwardCompatibility: 'autoZoomOut',
'limit-zoom': 'limitZoom',
limitZoomBackwardCompatibility: 'limitZoom',
};

View file

@ -28,19 +28,19 @@ export class Touches {
isMousedown = false;
_touchListeners: any = {
"touchstart": "handleTouchstart",
"touchmove": "handleTouchmove",
"touchend": "handleTouchend"
}
touchstart: 'handleTouchstart',
touchmove: 'handleTouchmove',
touchend: 'handleTouchend',
};
_mouseListeners: any = {
"mousedown": "handleMousedown",
"mousemove": "handleMousemove",
"mouseup": "handleMouseup",
"wheel": "handleWheel"
}
mousedown: 'handleMousedown',
mousemove: 'handleMousemove',
mouseup: 'handleMouseup',
wheel: 'handleWheel',
};
_otherListeners: any = {
"resize": "handleResize"
}
resize: 'handleResize',
};
get touchListeners() {
return this.properties.touchListeners ? this.properties.touchListeners : this._touchListeners;
@ -83,22 +83,22 @@ export class Touches {
const handler: MouseHandler = listeners[listener];
// Window
if (listener === "resize") {
if (listener === 'resize') {
if (action === 'addEventListener') {
window.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
window.removeEventListener(listener, this[handler], false);
}
// Document
} else if (listener === 'mouseup' || listener === "mousemove") {
// Document
} else if (listener === 'mouseup' || listener === 'mousemove') {
if (action === 'addEventListener') {
document.addEventListener(listener, this[handler], false);
}
if (action === 'removeEventListener') {
document.removeEventListener(listener, this[handler], false);
}
// Element
// Element
} else {
if (action === 'addEventListener') {
this.element.addEventListener(listener, this[handler], false);
@ -134,9 +134,8 @@ export class Touches {
this.getTouchstartPosition(event);
}
this.runHandler("touchstart", event);
}
this.runHandler('touchstart', event);
};
/* Touchmove */
@ -145,14 +144,14 @@ export class Touches {
// Pan
if (this.detectPan(touches)) {
this.runHandler("pan", event);
this.runHandler('pan', event);
}
// Pinch
if (this.detectPinch(event)) {
this.runHandler("pinch", event);
this.runHandler('pinch', event);
}
}
};
handleLinearSwipe(event: any) {
//event.preventDefault();
@ -172,7 +171,6 @@ export class Touches {
}
}
/* Touchend */
handleTouchend = (event: any) => {
@ -180,21 +178,20 @@ export class Touches {
// Double Tap
if (this.detectDoubleTap()) {
this.runHandler("double-tap", event);
this.runHandler('double-tap', event);
}
// Tap
this.detectTap();
this.runHandler("touchend", event);
this.runHandler('touchend', event);
this.eventType = 'touchend';
if (touches && touches.length === 0) {
this.eventType = undefined;
this.i = 0;
}
}
};
/* Mousedown */
@ -207,69 +204,62 @@ export class Touches {
this.getMousedownPosition(event);
}
this.runHandler("mousedown", event);
}
this.runHandler('mousedown', event);
};
/* Mousemove */
handleMousemove = (event: any) => {
//event.preventDefault();
if (!this.isMousedown) {
return;
}
// Pan
this.runHandler("pan", event);
this.runHandler('pan', event);
// Linear swipe
switch (this.detectLinearSwipe(event)) {
case "horizontal-swipe":
event.swipeType = "horizontal-swipe";
this.runHandler("horizontal-swipe", event);
case 'horizontal-swipe':
event.swipeType = 'horizontal-swipe';
this.runHandler('horizontal-swipe', event);
break;
case "vertical-swipe":
event.swipeType = "vertical-swipe";
this.runHandler("vertical-swipe", event);
case 'vertical-swipe':
event.swipeType = 'vertical-swipe';
this.runHandler('vertical-swipe', event);
break;
}
// Linear swipe
if (this.detectLinearSwipe(event) ||
this.eventType === 'horizontal-swipe' ||
this.eventType === 'vertical-swipe') {
if (this.detectLinearSwipe(event) || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
this.handleLinearSwipe(event);
}
}
};
/* Mouseup */
handleMouseup = (event: any) => {
// Tap
this.detectTap();
this.isMousedown = false;
this.runHandler("mouseup", event);
this.runHandler('mouseup', event);
this.eventType = undefined;
this.i = 0;
}
};
/* Wheel */
handleWheel = (event: any) => {
this.runHandler("wheel", event);
}
this.runHandler('wheel', event);
};
/* Resize */
handleResize = (event: any) => {
this.runHandler("resize", event);
}
this.runHandler('resize', event);
};
runHandler(eventName: any, response: any) {
if (this.handlers[eventName]) {
@ -277,13 +267,12 @@ export class Touches {
}
}
/*
* Detection
*/
detectPan(touches: any) {
return touches.length === 1 && !this.eventType || this.eventType === 'pan';
return (touches.length === 1 && !this.eventType) || this.eventType === 'pan';
}
detectDoubleTap() {
@ -318,9 +307,9 @@ export class Touches {
if (tapLength > 0) {
if (tapLength < this.tapMinTimeout) {
this.runHandler("tap", {});
this.runHandler('tap', {});
} else {
this.runHandler("longtap", {});
this.runHandler('longtap', {});
}
}
}
@ -334,7 +323,7 @@ export class Touches {
const touches = event.touches;
if (touches) {
if (touches.length === 1 && !this.eventType || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
if ((touches.length === 1 && !this.eventType) || this.eventType === 'horizontal-swipe' || this.eventType === 'vertical-swipe') {
return this.getLinearSwipeType(event);
}
} else {
@ -351,7 +340,7 @@ export class Touches {
const movementX = Math.abs(this.moveLeft(0, event) - this.startX);
const movementY = Math.abs(this.moveTop(0, event) - this.startY);
if ((movementY * 3) > movementX) {
if (movementY * 3 > movementX) {
return 'vertical-swipe';
} else {
return 'horizontal-swipe';
@ -397,11 +386,11 @@ export class Touches {
detectTouchScreen() {
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var mq = function(query: any) {
var mq = function (query: any) {
return window.matchMedia(query).matches;
}
};
if (('ontouchstart' in window)) {
if ('ontouchstart' in window) {
return true;
}
@ -411,11 +400,10 @@ export class Touches {
return mq(query);
}
/* Public properties and methods */
on(event: EventType, handler: Function) {
if (event) {
this.handlers[event] = handler;
}
}
}
}

View file

@ -3,23 +3,21 @@
import 'zone.js/dist/zone';
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
context(
path: string,
deep?: boolean,
filter?: RegExp
): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.

View file

@ -1,25 +1,19 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"exclude": ["src/test.ts", "**/*.spec.ts"]
}

View file

@ -1,10 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"enableIvy": false
}
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"enableIvy": false
}
}

View file

@ -1,17 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": ["jasmine"]
},
"files": ["src/test.ts"],
"include": ["**/*.spec.ts", "**/*.d.ts"]
}

View file

@ -4,7 +4,7 @@ import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule { }
export class AppRoutingModule {}

View file

@ -2,184 +2,241 @@
<h1>Properties</h1>
<!-- transition-duration -->
<div class="demo">
<h2>transition-duration: 1000</h2>
<p>Defines the speed of the animation of positioning and transforming.</p>
<pinch-zoom [transition-duration]="1000">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>transition-duration: 1000</h2>
<p>Defines the speed of the animation of positioning and transforming.</p>
<pinch-zoom [transition-duration]="1000">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- limit-zoom -->
<div class="demo">
<h2>limit-zoom: 2</h2>
<p>Limit the maximum available scale. By default, the maximum scale is calculated based on the original image size.</p>
<pinch-zoom [limit-zoom]="2">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>limit-zoom: 2</h2>
<p>Limit the maximum available scale. By default, the maximum scale is calculated based on the original image size.</p>
<pinch-zoom [limit-zoom]="2">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- minScale -->
<div class="demo">
<h2>minScale: 1</h2>
<p>Limit the minimum acceptable scale. With a value of 1, it is recommended to use this parameter with limitPan.</p>
<pinch-zoom [minScale]="1">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>minScale: 1</h2>
<p>Limit the minimum acceptable scale. With a value of 1, it is recommended to use this parameter with limitPan.</p>
<pinch-zoom [minScale]="1">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- auto-zoom-out -->
<div class="demo">
<h2>auto-zoom-out: true</h2>
<p>Automatic restoration of the original size of an image after its zooming in by two fingers.</p>
<pinch-zoom [auto-zoom-out]="true">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>auto-zoom-out: true</h2>
<p>Automatic restoration of the original size of an image after its zooming in by two fingers.</p>
<pinch-zoom [auto-zoom-out]="true">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- double-tap -->
<div class="demo">
<h2>double-tap: false</h2>
<p>Zooming in and zooming out of an image, depending on its current condition, with double tap.</p>
<pinch-zoom [double-tap]="false">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>double-tap: false</h2>
<p>Zooming in and zooming out of an image, depending on its current condition, with double tap.</p>
<pinch-zoom [double-tap]="false">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- double-tap-scale -->
<div class="demo">
<h2>double-tap-scale: 4</h2>
<p>Double tap scaling factor.</p>
<pinch-zoom [double-tap-scale]="4">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>double-tap-scale: 4</h2>
<p>Double tap scaling factor.</p>
<pinch-zoom [double-tap-scale]="4">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- disabled -->
<div class="demo">
<h2>disabled: true</h2>
<pinch-zoom [disabled]="true">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>disabled: true</h2>
<pinch-zoom [disabled]="true">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- disablePan -->
<div class="demo">
<h2>disablePan: true</h2>
<p>Turn off panning with one finger.</p>
<pinch-zoom [disablePan]="true">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>disablePan: true</h2>
<p>Turn off panning with one finger.</p>
<pinch-zoom [disablePan]="true">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- minPanScale -->
<div class="demo">
<h2>minPanScale: 2</h2>
<p>Minimum zoom at which panning is enabled.</p>
<pinch-zoom [minPanScale]="2">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>minPanScale: 2</h2>
<p>Minimum zoom at which panning is enabled.</p>
<pinch-zoom [minPanScale]="2">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- overflow -->
<div class="demo">
<h2>overflow: 'visible'</h2>
<p>hidden - the overflow is clipped, and the rest of the content will be invisible. visible - the overflow is not clipped. The content renders outside the element's box.</p>
<pinch-zoom [overflow]="'visible'">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>overflow: 'visible'</h2>
<p>
hidden - the overflow is clipped, and the rest of the content will be invisible. visible - the overflow is not clipped. The
content renders outside the element's box.
</p>
<pinch-zoom [overflow]="'visible'">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- disableZoomControl -->
<div class="demo">
<h2>disableZoomControl: 'disable'</h2>
<p>Disable zoom controls. auto - Disable zoom controls on touch screen devices. never - show zoom controls on all devices. disable - disable zoom controls on all devices.</p>
<pinch-zoom [disableZoomControl]="'disable'">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>disableZoomControl: 'disable'</h2>
<p>
Disable zoom controls. auto - Disable zoom controls on touch screen devices. never - show zoom controls on all devices. disable
- disable zoom controls on all devices.
</p>
<pinch-zoom [disableZoomControl]="'disable'">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- zoomControlScale -->
<div class="demo">
<h2>zoomControlScale: 2</h2>
<p>Zoom factor when using zoom controls.</p>
<pinch-zoom [zoomControlScale]="2">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>zoomControlScale: 2</h2>
<p>Zoom factor when using zoom controls.</p>
<pinch-zoom [zoomControlScale]="2">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- backgroundColor -->
<div class="demo">
<h2>backgroundColor: 'rgba(0,0,0,0.65)'</h2>
<p>The background color of the container.</p>
<pinch-zoom [backgroundColor]="'rgba(0,0,0,0.65)'">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>backgroundColor: 'rgba(0,0,0,0.65)'</h2>
<p>The background color of the container.</p>
<pinch-zoom [backgroundColor]="'rgba(0,0,0,0.65)'">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- limitPan -->
<div class="demo">
<h2>limitPan: true</h2>
<p>Stop panning when the edge of the image reaches the edge of the screen.</p>
<pinch-zoom [limitPan]="true">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>limitPan: true</h2>
<p>Stop panning when the edge of the image reaches the edge of the screen.</p>
<pinch-zoom [limitPan]="true">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- listeners -->
<div class="demo">
<h2>listeners: 'auto'</h2>
<p>By default, subscriptions are made for mouse and touch screen events. The value auto means that the subscription will be only for touch events or only for mouse events, depending on the type of screen.</p>
<pinch-zoom [listeners]="'auto'">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>listeners: 'auto'</h2>
<p>
By default, subscriptions are made for mouse and touch screen events. The value auto means that the subscription will be only
for touch events or only for mouse events, depending on the type of screen.
</p>
<pinch-zoom [listeners]="'auto'">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- wheel -->
<div class="demo">
<h2>wheel: false</h2>
<p>Scale with the mouse wheel.</p>
<pinch-zoom [wheel]="false">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>wheel: false</h2>
<p>Scale with the mouse wheel.</p>
<pinch-zoom [wheel]="false">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- wheelZoomFactor -->
<div class="demo">
<h2>wheelZoomFactor: 0.5</h2>
<p>Zoom factor when zoomed in with the mouse wheel.</p>
<pinch-zoom [wheelZoomFactor]="0.5">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<div class="demo">
<h2>wheelZoomFactor: 0.5</h2>
<p>Zoom factor when zoomed in with the mouse wheel.</p>
<pinch-zoom [wheelZoomFactor]="0.5">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
<!-- autoHeight -->
<div class="demo">
<h2>autoHeight: true</h2>
<p>Calculate the height of the container based on the width and height attributes of the image. By default, the width of the container is 100%, and the height is determined after the image information is loaded - this may cause a delay in determining the height of the container. If you want the container to initially have dimensions corresponding to the dimensions of the image, then specify the attributes width and height for the <img> tag. When setting the property value to `true`, a subscription to the window resize listener will be created.</p>
<pinch-zoom [autoHeight]="true">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80" width="752" height="500">
</pinch-zoom>
</div>
<div class="demo">
<h2>autoHeight: true</h2>
<p>
Calculate the height of the container based on the width and height attributes of the image. By default, the width of the
container is 100%, and the height is determined after the image information is loaded - this may cause a delay in determining
the height of the container. If you want the container to initially have dimensions corresponding to the dimensions of the
image, then specify the attributes width and height for the <img /> tag. When setting the property value to `true`, a
subscription to the window resize listener will be created.
</p>
<pinch-zoom [autoHeight]="true">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
width="752"
height="500"
/>
</pinch-zoom>
</div>
<!-- draggableImage -->
<div class="demo">
<h2>draggableImage: true</h2>
<p>Sets the attribute draggable to the img tag.</p>
<pinch-zoom [draggableImage]="true">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
</div>
<!-- Methods -->
<h1>Methods</h1>
<div class="demo">
<pinch-zoom #myPinch="pinchZoom">
<img src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80">
</pinch-zoom>
<div class="actions">
<button class="btn btn-small btn-outline btn-rounded" (click)="myPinch.toggleZoom()">toggleZoom()</button>
<button class="btn btn-small btn-outline btn-rounded" (click)="myPinch.destroy()">destroy()</button>
<div class="demo">
<h2>draggableImage: true</h2>
<p>Sets the attribute draggable to the img tag.</p>
<pinch-zoom [draggableImage]="true">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
</div>
</div>
</div>
<!-- Methods -->
<h1>Methods</h1>
<div class="demo">
<pinch-zoom #myPinch="pinchZoom">
<img
src="https://images.unsplash.com/photo-1577234162223-98e9caa94705?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=752&q=80"
/>
</pinch-zoom>
<div class="actions">
<button class="btn btn-small btn-outline btn-rounded" (click)="myPinch.toggleZoom()">toggleZoom()</button>
<button class="btn btn-small btn-outline btn-rounded" (click)="myPinch.destroy()">destroy()</button>
</div>
</div>
</div>

View file

@ -4,22 +4,22 @@ import { AppComponent } from './app.component';
import { PinchZoomModule } from '../../projects/ngx-pinch-zoom/src/lib/pinch-zoom.module';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RouterTestingModule, PinchZoomModule],
declarations: [AppComponent],
}).compileComponents();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RouterTestingModule, PinchZoomModule],
declarations: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'ivypinchApp'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('ivypinchApp');
});
it(`should have as title 'ivypinchApp'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('ivypinchApp');
});
});

View file

@ -1,10 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.sass']
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.sass'],
})
export class AppComponent {
title = 'ivypinchApp';
title = 'ivypinchApp';
}

View file

@ -6,9 +6,9 @@ import { AppComponent } from './app.component';
import { PinchZoomModule } from '../../projects/ngx-pinch-zoom/src/lib/pinch-zoom.module';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule, PinchZoomModule],
providers: [],
bootstrap: [AppComponent],
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule, PinchZoomModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}

View file

@ -1,3 +1,3 @@
export const environment = {
production: true
production: true,
};

View file

@ -3,7 +3,7 @@
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
production: false,
};
/*

View file

@ -1,13 +1,13 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>IvypinchApp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
<head>
<meta charset="utf-8" />
<title>IvypinchApp</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<app-root></app-root>
</body>
</html>

View file

@ -5,8 +5,9 @@ import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));

View file

@ -57,8 +57,7 @@
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS

View file

@ -2,23 +2,21 @@
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
context(
path: string,
deep?: boolean,
filter?: RegExp
): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.

View file

@ -1,15 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": ["src/main.ts", "src/polyfills.ts"],
"include": ["src/**/*.d.ts"]
}

View file

@ -11,20 +11,12 @@
"moduleResolution": "node",
"importHelpers": true,
"paths": {
"ngx-pinch-zoom": [
"dist/ngx-pinch-zoom/ngx-pinch-zoom",
"dist/ngx-pinch-zoom"
]
"ngx-pinch-zoom": ["dist/ngx-pinch-zoom/ngx-pinch-zoom", "dist/ngx-pinch-zoom"]
},
"target": "es2015",
"module": "es2020",
"lib": [
"es2018",
"dom"
],
"types": [
"node"
]
"lib": ["es2018", "dom"],
"types": ["node"]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false

View file

@ -1,18 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jasmine"]
},
"files": ["src/test.ts", "src/polyfills.ts"],
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}