Giter Site home page Giter Site logo

ngx-capture's Introduction

NGX-CAPTURE

npm version

Screen capture library for Angular. Define a zone and it will capture it and return a string containing a base64 PNG.

Or download the result file.

Stackblitz Example

Angular 8 > npm install [email protected]

Angular 9 > npm install [email protected]

Angular 10+ > npm install ngx-capture

💪 If you like this library, you can buy me a coffee here!

Example

Install

npm install ngx-capture
import { NgModule } from '@angular/core';
import { NgxCaptureModule } from 'ngx-capture';

@NgModule({
  ...
  imports: [
    ...
    NgxCaptureModule,
  ],
})
export class AppModule {}

Define the screen capture area with a variable (eg. #screen):

<div #screen>
  <h1>Hey!</h1>
  <p>some content</p>
</div>

There are 4 ways to use this library

For a full element capture, use the service:

Each time you call the service, it will capture the whole content of the HTML element marked #screen

import { NgxCaptureService } from 'ngx-capture';
...
@ViewChild('screen', { static: true }) screen: any;

...
this.captureService.getImage(this.screen.nativeElement, true)
.pipe(
  tap(img => {
    console.log(img);
  })
).subscribe();

For the entire BODY

This will capture the full page

this.captureService
  .getImage(document.body, true)
  .pipe(
    tap((img) => {
      console.log(img);
    })
  )
  .subscribe();

To access crop options, use the component

This will allow you to click and drag to select the area you want to capture.

ex: https://ngx-capture-example-component.stackblitz.io

import { Component } from '@angular/core';

@Component({
  selector: 'app',
  template: `
    ...
    <ngx-capture [target]="screen" (resultImage)="saveImage($event)"></ngx-capture>
  `,
})
export class AppComponent {
  saveImage(img: string) {
    console.log(img);
  }
}

Using crop options freely

This way, you can set a specific area to capture.

this.captureService
  .getImage(this.screen.nativeElement, false, {
    x: 50,
    y: 150,
    width: 50,
    height: 50,
  })
  .pipe(tap((img) => (this.img = img)))
  .subscribe();

Download the result directly

Once you have the image as a string, you can pass it to the downloadImage method to download it.

this.captureService
  .getImage(document.body, true)
  .pipe(
    tap((img) => {
      console.log(img);
    }),
    tap((img) => this.captureService.downloadImage(img))
  )
  .subscribe();

ngx-capture's People

Contributors

dependabot[bot] avatar frustrusse avatar prograk avatar wanchai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ngx-capture's Issues

unable to capture img with [src]

Thanks for the library. Liked it.

One minor bug noticed is that it is not capturing img with [src] tag.
<img [src]="dynamicLogo">

Use it on ionic v6

Hello, i use the ngx-capture on ionic and i have the error following :

Unhandled Promise rejection: Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Sharing constructed stylesheets in multiple documents is not allowed ; Zone: <root> ; Task: null ; Value: DOMException: Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Sharing constructed stylesheets in multiple documents is not allowed
    at addStyle (http://localhost/vendor.js:10957:45)
    at attachStyles (http://localhost/vendor.js:10969:19)
    at http://localhost/vendor.js:12111:7
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (http://localhost/vendor.js:122230:24)
    at _next (http://localhost/vendor.js:122252:9)
    at http://localhost/vendor.js:122259:7
    at new ZoneAwarePromise (http://localhost/polyfills.js:1353:33)
    at http://localhost/vendor.js:122248:12
    at updateComponent (http://localhost/vendor.js:12147:17) Error: Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Sharing constructed stylesheets in multiple documents is not allowed
    at addStyle (http://localhost/vendor.js:10957:45)
    at attachStyles (http://localhost/vendor.js:10969:19)
    at http://localhost/vendor.js:12111:7
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (http://localhost/vendor.js:122230:24)
    at _next (http://localhost/vendor.js:122252:9)
    at http://localhost/vendor.js:122259:7
    at new ZoneAwarePromise (http://localhost/polyfills.js:1353:33)
    at http://localhost/vendor.js:122248:12
    at updateComponent (http://localhost/vendor.js:12147:17)

if you have any suggestion to resolve the problem

Issue with new lines

I'm using the library to capture the input of an textarea which has new lines separator '\n'.
When i see the text in area it shows like this
"hey
this
is
on
a
new
line"

and the captured photo shows it in a one-liner. See attached photo below.
ngx-capture issue

Routed components are not in the screenshot

Hi there,

I want to takes screenshots of an selected area width that:
<ngx-capture [target]="screen" (resultImage)="saveImage($event)"></ngx-capture>

The screenshot is taken and the header and navbar is shown, but it doesn't show the routed components.
My code:
app.component.html

<div #screen class="container-fluid">
  @if (takeScreenshot)
  {
    <!--<ngx-capture [target]="screen" (resultImage)="saveImage($event)"></ngx-capture>-->
  }
  <img id="myimage" [src]='picture' />
  <!-- Navigation -->
  <app-system-navbar-nd></app-system-navbar-nd>

  <!-- Main -->
  <main [@routeAnimations]="o && o.activatedRouteData">
      <router-outlet #o="outlet"></router-outlet>
  </main>
</div>

app.component.ts:

  saveImage(img: string) {
    console.log(img);
    let blob = this.DataURIToBlob(img);
    this.createImageFromBlob(blob);
  }

  doScreenshot()
  {
    this.captureService.getImage(this.screen.nativeElement, true).subscribe((img) => {
      let blob = this.DataURIToBlob(img);
      this.createImageFromBlob(blob);
      //this.objectURL = 'data:image/jpeg;base64,' + this.picture.img;
      //console.log(this.objectURL);
    });
    this.takeScreenshot = true;
  }

  DataURIToBlob(dataURI: string)
  {
    const splitDataURI = dataURI.split(',');
    const byteString = splitDataURI[0].indexOf('base64') >= 0 ? atob(splitDataURI[1]) : decodeURI(splitDataURI[1]);
    const mimeString = splitDataURI[0].split(':')[1].split(';')[0];
    
    const ia = new Uint8Array(byteString.length);
    for (let i = 0; i < byteString.length; i++)
        ia[i] = byteString.charCodeAt(i);

    return new Blob([ia], { type: mimeString });
  }

  createImageFromBlob(image: Blob)
  {
    let reader = new FileReader();
    reader.addEventListener("load", () => {
      this.picture = reader.result;
    }, false);

    if (image) {
      reader.readAsDataURL(image);
    }
  }

If I try to take the whole body, there is the same problem.
I didn't find something about this via google, know someone what's going wrong here?

Thank you very much

How to set output size?

I need to get custom size for the image capture. Is there any way I can set image size of the output without affecting the view and has good quality?

How to catch all screen?

Hi,
Would you please provide an example, as for how to capture 100% of the body?

The examples provided show how to capture the screen through one of the components. When attaching #screen to the lowest-level element (such as the first div in app.component.ts) you still miss out on your screenshot everything that appends directly to the body, outside of the application root.

Example for stuff that stay out of the screenshot: Toast messages, dialogs, modals, selection boxes that appended to the body for fixed positioning etc.

Thanks

Error configuring it

Hi Creator and mantainers,

Firsf ot all thanks for the library, I request some support to understand what may happens.

I followed the simple instructions that I can find in the README, however I'm facing a weird issue when building

Error: node_modules/ngx-capture/lib/ngx-capture.component.d.ts:29:18 - error TS2707: Generic type 'ɵɵComponentDeclaration' requires between 7 and 8 type arguments.
29 static ɵcmp: i0.ɵɵComponentDeclaration<NgxCaptureComponent, "ngx-capture", never, { "target": "target"; }, { "resultImage": "resultImage"; }, never, ["*"], false, never>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I'm trying to set up in a project using Angular 14.2.0.

Do you know what can be happening?

Thanks in advance

Reference files:

package.json

{
  "name": "example-project",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --port 4400",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.2.0",
    "@angular/cdk": "^14.2.0",
    "@angular/common": "^14.2.0",
    "@angular/compiler": "^14.2.0",
    "@angular/core": "^14.2.0",
    "@angular/forms": "^14.2.0",
    "@angular/material": "^14.2.0",
    "@angular/platform-browser": "^14.2.0",
    "@angular/platform-browser-dynamic": "^14.2.0",
    "@angular/router": "^14.2.0",
    "ngx-capture": "^0.13.0",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.10",
    "@angular/cli": "~14.2.10",
    "@angular/compiler-cli": "^14.2.0",
    "@types/jasmine": "~4.0.0",
    "jasmine-core": "~4.3.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.0.0",
    "ng-packagr": "^14.2.0",
    "typescript": "~4.7.2"
  }
}

app.module.ts

@NgModule({
    declarations: [
        AppComponent
    ],
    providers: [],
    bootstrap: [AppComponent],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        AppRoutingModule,
        HttpClientModule,
        MatButtonModule,       
        NgxCaptureModule
    ]
})
export class AppModule { }

app.component.html

<div #screen>
  <!-- Other stuff... -->

  <router-outlet></router-outlet>
</div>

Capture overlay is not limited to the target element

When I set the target element as an inner element of the whole document, I expect that the overlay and the crop options just be enabled and limited to that element, but the overlay is the same height and width of the window, and changing it cause calculated crop area to be wrong. could someone help me with this?

Getting null image in saveImage function.

Hi,

I used this library and it installed without any error. But when i tried to capture the screen, In saveImage function the img parameter is getting value null. No idea what i am doing wrong.

Would it be possible ngx-capture support another image type than PNG ?

Hi,

Congrat' for this amazing lib !! :)

I have a request :
For now, ngx-capture support only PNG image types.
Would it be possible to add a new settings option allowing to specify image type ?
Some parts of webapps could contain SVG into the DOM for example, and these parts can not be well captured.

In my case, I have an SVG cross icon in my webapp that is minimized when i captured it HTML element.

Thanks,

Error: InvalidStateError: Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0.

When I use ngx-capture on page where exists disabled input using angular material design I'm getting following error:
core.js:5980 ERROR Error: Error: InvalidStateError: Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0.
at ngx-capture.js:29
at ZoneDelegate.invoke (zone-evergreen.js:364)
at Object.onInvoke (core.js:28301)
at ZoneDelegate.invoke (zone-evergreen.js:363)
at Zone.run (zone-evergreen.js:123)
at zone-evergreen.js:857
at ZoneDelegate.invokeTask (zone-evergreen.js:399)
at Object.onInvokeTask (core.js:28289)
at ZoneDelegate.invokeTask (zone-evergreen.js:398)
at Zone.runTask (zone-evergreen.js:167)

HTML:

<div #screen>
  <mat-form-field class="example-full-width">
    <mat-label>Some label (disabled)</mat-label>
    <input matInput disabled value="Some value">
  </mat-form-field>
  <div>
    <button (click)="onClick($event)">Captured</button>
  </div>
</div>

TS:

import { Component, ViewChild, ElementRef, EventEmitter, OnInit } from '@angular/core';
import { tap } from 'rxjs/operators';
import { NgxCaptureService } from 'ngx-capture';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'test';
  txtdisabled: boolean;

  @ViewChild('screen', { static: true }) screen: any;

  constructor(private captureService: NgxCaptureService) {
    this.txtdisabled = true;
  }

  onClick(e: MouseEvent): void {
    this.captureService.getImage(this.screen.nativeElement, true)
    .pipe(
      tap(img => {
        console.log(img);
      })
    ).subscribe();
  }
}

I'm using chrome browser Version 90.0.4430.212 (Official Build) (64-bit).
In case when I use firefox browser it seems that everything is OK.

Error: TypeError: undefined is not an object (evaluating 'element.ownerDocument')

I'm using ngx Capture to take screenshot in Ionic v4 App but it's not working

Version in package json "ngx-capture": "^0.10.2"

My code
this.captureService.getImage(this.screen.nativeElement, true).toPromise().then(img => { console.log("NGx Capture -> ", img); let encodedURI = encodeURI(img); });

Any help will be helpful. Thank you

Recording the web page

Hi, how to do the recording video for what happening in the page without open the webcam . For example the page have real time data and other video content just recording what happen in the page when user click the start button.

Capture an iframe

Hello ! nice package !

There is no possibility of capturing an iframe that is inside the element that is being captured??

width and height not in px

Hi, when launching the project from different computers the crop options I set generate different size images from different computers / browsers.
Nowhere in the doc is it specified what unit of measurement the width and height are in, could you provide it ?
Thanks in advance

ngx-capture on angular 11: unable to resolve dependancy tree

Hello,

When I try to install ngx-capture via npm npm install ngx-capture I get the following error:

`npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: @angular/[email protected]
npm ERR! node_modules/@angular/common
npm ERR! @angular/common@"~11.1.1" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @angular/common@"^10.0.0" from [email protected]
npm ERR! node_modules/ngx-capture
npm ERR! ngx-capture@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users<username>\AppData\Local\npm-cache\eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users<username>\AppData\Local\npm-cache_logs\2021-10-22T06_46_38_106Z-debug.log`

In the eresolve-report.txt there is this code:
{ "code": "ERESOLVE", "current": { "name": "@angular/common", "version": "11.1.2", "whileInstalling": { "name": "xxx", "version": "0.0.0", "path": "C:\\xampp\\htdocs\\xxx" }, "location": "node_modules/@angular/common", "dependents": [ { "type": "prod", "name": "@angular/common", "spec": "~11.1.1", "from": { "location": "C:\\xampp\\htdocs\\xxx" } } ] }, "edge": { "type": "peer", "name": "@angular/common", "spec": "^10.0.0", "error": "INVALID", "from": { "name": "ngx-capture", "version": "0.12.0", "whileInstalling": { "name": "xxx", "version": "0.0.0", "path": "C:\\xampp\\htdocs\\xxx" }, "location": "node_modules/ngx-capture", "dependents": [ { "type": "prod", "name": "ngx-capture", "spec": "*", "from": { "location": "C:\\xampp\\htdocs\\xxxl" } } ] } }, "peerConflict": null, "strictPeerDeps": false, "force": false }
I've crossed out my username and the project name.
What should I do?

DOMException: Failed to set the 'adoptedStyleSheets'

Hi, I try to implement to ngx-capture in an ionic 6 page, but copying the code in the wright place delivers:

Uncaught (in promise) DOMException: Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Sharing constructed stylesheets in multiple documents is not allowed
    at addStyle (http://localhost:8101/vendor.js:96476:51)
    at attachStyles (http://localhost:8101/vendor.js:96486:21)
    at updateComponent (http://localhost:8101/vendor.js:97462:9)
    at http://localhost:8101/vendor.js:97453:32
    at then (http://localhost:8101/vendor.js:97597:61)
    at dispatchHooks (http://localhost:8101/vendor.js:97453:12)
    at Array.dispatch (http://localhost:8101/vendor.js:97430:28)
    at consume (http://localhost:8101/vendor.js:98300:21)
    at flush (http://localhost:8101/vendor.js:98315:9)

Is this only a problem because I'm using ionic, or do I miss somehting?
Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.