Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: intersection-observer #82

Merged
merged 1 commit into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions apps/demo/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ export const appRoutes: Routes = [
(await import(`./pages/geolocation/geolocation-page.module`))
.GeolocationPageModule,
},
{
path: DemoPath.IntersectionObserverPage,
loadChildren: async () =>
(
await import(
`./pages/intersection-observer/intersection-observer-page.module`
)
).IntersectionObserverPageModule,
},
{
path: '',
redirectTo: DemoPath.HomePage,
Expand Down
1 change: 1 addition & 0 deletions apps/demo/src/app/constants/demo-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export enum DemoPath {
ResizeObserverPage = `resize-observer`,
CanvasPage = `canvas`,
GeolocationPage = `geolocation`,
IntersectionObserverPage = `intersection-observer`,
}
3 changes: 1 addition & 2 deletions apps/demo/src/app/pages/home/home-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,8 @@ <h2>Geolocation</h2>
/>
</a>
<a
href="https://github.com/ng-web-apis/intersection-observer"
target="_blank"
class="link"
[routerLink]="['/', link.IntersectionObserverPage]"
[class.not-supported]="!intersectionSupport"
>
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<section
*ngIf="support; else not"
waIntersectionRoot
waIntersectionObserver
waIntersectionThreshold="0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9"
class="wrapper"
>
<h1
class="element"
[attr.data-ratio]="ratio"
(waIntersectionObservee)="onIntersection($event)"
>
I'm being observed
</h1>
</section>
<ng-template #not>
Your browser does not support Intersection Observer API
</ng-template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
:host {
perspective: 150vw;
user-select: none;
flex-direction: column;
align-items: center;
}

.wrapper {
position: relative;
height: 200px;
width: 80vw;
overflow: auto;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.2);

&:before {
content: '';
display: block;
height: 900px;
}
}

.element {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
top: 300px;
left: 10vw;
width: 60vw;
height: 200px;
transition: background 0.1s;

&[data-ratio='0'] {
background: #8591eb;
}

&[data-ratio='1'] {
background: #85a0eb;
}

&[data-ratio='2'] {
background: #84aeeb;
}

&[data-ratio='3'] {
background: #83beeb;
}

&[data-ratio='4'] {
background: #86d2eb;
}

&[data-ratio='5'] {
background: #87ddeb;
}

&[data-ratio='6'] {
background: #8ae5eb;
}

&[data-ratio='7'] {
background: #8bebdf;
}

&[data-ratio='8'] {
background: #83ebc8;
}

&[data-ratio='9'] {
background: #6beb99;
}

&[data-ratio='10'] {
background: #4ceb60;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {ChangeDetectionStrategy, Component, Inject} from '@angular/core';
import {INTERSECTION_OBSERVER_SUPPORT} from '@ng-web-apis/intersection-observer';

@Component({
selector: `intersection-observer-page`,
templateUrl: `./intersection-observer-page.component.html`,
styleUrls: [`./intersection-observer-page.component.less`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class IntersectionObserverPageComponent {
ratio = 0;

constructor(@Inject(INTERSECTION_OBSERVER_SUPPORT) readonly support: boolean) {}

onIntersection(intersections: IntersectionObserverEntry[]) {
this.ratio = Math.round(intersections[0].intersectionRatio * 10);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {NgModule} from '@angular/core';
import {IntersectionObserverModule} from '@ng-web-apis/intersection-observer';
import {RouterModule} from '@angular/router';
import {CommonModule} from '@angular/common';

import {IntersectionObserverPageComponent} from './intersection-observer-page.component';

@NgModule({
imports: [
CommonModule,
IntersectionObserverModule,
RouterModule.forChild([{path: '', component: IntersectionObserverPageComponent}]),
],
declarations: [IntersectionObserverPageComponent],
})
export class IntersectionObserverPageModule {}
60 changes: 60 additions & 0 deletions libs/intersection-observer/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Changelog

All notable changes to this project will be documented in this file. See
[standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [3.0.0](https://github.com/ng-web-apis/intersection-observer/compare/v2.1.0...v3.0.0) (2022-07-15)

### ⚠ BREAKING CHANGES

- update to Angular 12 and Ivy distribution
([90e166b](https://github.com/ng-web-apis/intersection-observer/commit/90e166b7404f2e6edac8713dfbb56cd344e861f7))

## [2.1.0](https://github.com/ng-web-apis/intersection-observer/compare/v2.0.1...v2.1.0) (2020-09-19)

### Features

- **directive:** add `exportAs` ([8341df3](https://github.com/ng-web-apis/intersection-observer/commit/8341df3))

### [2.0.1](https://github.com/ng-web-apis/intersection-observer/compare/v2.0.0...v2.0.1) (2020-08-26)

### Bug Fixes

- **service:** fix exception in Internet Explorer
([5f28df4](https://github.com/ng-web-apis/intersection-observer/commit/5f28df4))

## [2.0.0](https://github.com/ng-web-apis/intersection-observer/compare/v1.1.3...v2.0.0) (2020-05-15)

### Features

- **observer:** Add new directives and service to create single observer and observe multiple elements, rename old
directive ([c2de2ff](https://github.com/ng-web-apis/intersection-observer/commit/c2de2ff))

BREAKING CHANGE: New directives names and mechanics

### [1.1.3](https://github.com/ng-web-apis/intersection-observer/compare/v1.1.2...v1.1.3) (2020-04-24)

- add default values for tokens and remove @Optional

### [1.1.2](https://github.com/ng-web-apis/intersection-observer/compare/v1.1.1...v1.1.2) (2020-04-06)

### Bug Fixes

- **directive:** add attributes to constructor to make code completion work in IDE
([ec3c25a](https://github.com/ng-web-apis/intersection-observer/commit/ec3c25a))

### [1.1.1](https://github.com/ng-web-apis/intersection-observer/compare/v1.1.0...v1.1.1) (2020-03-30)

### Bug Fixes

- **service:** only observe when there are subscriptions
([2a8e267](https://github.com/ng-web-apis/intersection-observer/commit/2a8e267))

## [1.1.0](https://github.com/ng-web-apis/intersection-observer/compare/v1.0.0...v1.1.0) (2020-03-26)

### Features

- **service:** add `IntersectionObserverService`
([65e79aa](https://github.com/ng-web-apis/intersection-observer/commit/65e79aa))

## 1.0.0 (2020-03-25)
21 changes: 21 additions & 0 deletions libs/intersection-observer/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Alexander Inkin <alexander@inkin.ru>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
136 changes: 136 additions & 0 deletions libs/intersection-observer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# ![ng-web-apis logo](logo.svg) Intersection Observer API for Angular

[![npm version](https://img.shields.io/npm/v/@ng-web-apis/intersection-observer.svg)](https://npmjs.com/package/@ng-web-apis/intersection-observer)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/@ng-web-apis/intersection-observer)](https://bundlephobia.com/result?p=@ng-web-apis/intersection-observer)

This is a library for declarative use of
[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) with Angular.

## Install

If you do not have [@ng-web-apis/common](https://github.com/ng-web-apis/common):

```
npm i @ng-web-apis/common
```

Now install the package:

```
npm i @ng-web-apis/intersection-observer
```

## Usage

1. Import `IntersectionObserverModule` for directives to work
2. Create [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) with
`waIntersectionObserver` directive
3. Observe elements with `waIntersectionObservee` directive
4. _Optional:_ provide root element with `waIntersectionRoot` directive and use `waIntersectionThreshold` and
`waIntersectionRootMargin` attributes to configure
[IntersectionObserver options](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver)

> **NOTE:** Keep in mind these are used one time in constructor so you cannot use binding, only strings. Pass comma
> separated numbers to set an array of thresholds.

### Usage with Jest

DOM environment provided by Jest does not emulate IntersectionObserver API and need to be mocked. You can add the
following line to your `setup.ts`:

```ts
// setup.ts
import '@ng-web-apis/universal/mocks';
```

to use mocks from [@ng-web-apis/universal](https://github.com/ng-web-apis/universal) package.

## Examples

Observing multiple elements intersecting with viewport using single observer

```html
<section waIntersectionObserver waIntersectionThreshold="0.5">
<div (waIntersectionObservee)="onIntersection($event)">I'm being observed</div>
<div (waIntersectionObservee)="onIntersection($event)">I'm being observed</div>
</section>
```

Observing elements intersecting with parent element, each having different configuration therefore using individual
observers:

```html
<section waIntersectionRoot>
<div waIntersectionObserver waIntersectionThreshold="0.5" (waIntersectionObservee)="onIntersection($event)">
I'm being observed
</div>
<div waIntersectionObserver waIntersectionThreshold="1,0.5,0" (waIntersectionObservee)="onIntersection($event)">
I'm being observed
</div>
</section>
```

## Services

Alternatively you can use `Observable`-based services:

1. `IntersectionObserveeService` can be used to observe elements under `waIntersectionObserver` directive in the DI tree

2. `IntersectionObserverService` can be used to observe single element independently. Provide tokens manually to
configure it:

```typescript
@Component({
selector: 'my-component',
providers: [
IntersectionObserverService,
{
provide: INTERSECTION_THRESHOLD,
useValue: 0.5,
},
{
provide: INTERSECTION_ROOT_MARGIN,
useValue: '10px',
},
],
})
export class MyComponent {
constructor(@Inject(IntersectionObserverService) entries$: IntersectionObserverService) {
entries$.subscribe(entries => {
// Don't forget to unsubscribe
console.log(entries);
});
}
}
```

> In this case provide `INTERSECTION_ROOT` up the DI tree if you want to observe intersection with a particular parent
> element

## Browser support

| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/) |
| :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| 15+ | 55+ | 51+ | 12.2+ |

> You can use [polyfill](https://www.npmjs.com/package/intersection-observer) to support older browsers

## Angular Universal

If you want to use this package with SSR, you need to mock `IntersectionObserver` class on the server. You can use our
Universal package for this, see [this example](https://github.com/ng-web-apis/universal#mocks).

## Demo

You can [try online demo here](https://ng-web-apis.github.io/intersection-observer)

## See also

Other [Web APIs for Angular](https://ng-web-apis.github.io/) by [@ng-web-apis](https://github.com/ng-web-apis)

## Open-source

Do you also want to open-source something, but hate the collateral work? Check out this
[Angular Open-source Library Starter](https://github.com/TinkoffCreditSystems/angular-open-source-starter) we’ve created
for our projects. It got you covered on continuous integration, pre-commit checks, linting, versioning + changelog, code
coverage and all that jazz.
Loading