Skip to content

Commit

Permalink
Created v1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Block committed Jul 16, 2024
1 parent bdb2b0c commit f76820e
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 76 deletions.
70 changes: 57 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,68 @@
# NgxWordMorph
# Ngx Word-Morph Component

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0.
`@omnedia/ngx-word-morph` is an Angular library designed to facilitate word morphing animations within Angular applications.

## Code scaffolding
## Features
- Morph words within your Angular application.
- Easily customizable.

Run `ng generate component component-name --project ngx-word-morph` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngx-word-morph`.
> Note: Don't forget to add `--project ngx-word-morph` or else it will be added to the default project in your `angular.json` file.
## Installation

## Build
Install the library using npm:

Run `ng build ngx-word-morph` to build the project. The build artifacts will be stored in the `dist/` directory.
```bash
npm install @omnedia/ngx-word-morph
```

## Publishing
## Usage

After building your library with `ng build ngx-word-morph`, go to the dist folder `cd dist/ngx-word-morph` and run `npm publish`.
Import the `NgxWordMorphComponent` in your Angular module:

## Running unit tests
```typescript
import { NgxWordMorphComponent } from '@omnedia/ngx-word-morph';

Run `ng test ngx-word-morph` to execute the unit tests via [Karma](https://karma-runner.github.io).
@Component({
...
imports: [
...
NgxWordMorphComponent,
],
...
})
```

## Further help
Use the component in your template:

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
```html
<om-word-morph [words]="['Hello', 'World']" styleClass="custom-class"></om-word-morph>
```

## API

```html
<om-word-morph
[words]="words"
[morphDuration]="morphDuration"
[morphDelay]="morphDelay"
styleClass="your-custom-class"
></om-word-morph>
```

Starts the word morphing effect.

- `words`: An array of strings to be animated.
- `morphDuration`: (optional): The duration of the morphing animation in milliseconds. Default is 1000.
- `morphDelay`: (optional): The delay between morphing one word to the next in milliseconds. Default is 5000.
- `styleClass`: (optional): Add a class to the `<div>` wrapper tag.

## Styling
If you want to style the text, do it globally via the `styleClass`. <br>
To change the font size make sure to change the `--om-word-morph-font-size` variable instead of directly changing the size.

## Contributing

Contributions are welcome. Please submit a pull request or open an issue to discuss your ideas.

## License

This project is licensed under the MIT License.
18 changes: 15 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
{
"name": "ngx-word-morph",
"version": "0.0.1",
"name": "@omnedia/ngx-word-morph",
"version": "1.0.0",
"peerDependencies": {
"@angular/common": "^17.3.0",
"@angular/core": "^17.3.0"
},
"dependencies": {
"tslib": "^2.3.0"
},
"sideEffects": false
"sideEffects": false,
"keywords": [
"rxjs",
"npm",
"morph",
"text",
"animation"
],
"repository": {
"url": "https://github.com/omnedia/ngx-word-morph"
},
"author": "Markus Block ([email protected])",
"license": "MIT"
}
22 changes: 22 additions & 0 deletions src/lib/ngx-word-morph.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="om-word-morph" [ngClass]="styleClass">
<div id="words" class="words">
<p id="text1"></p>
<p id="text2"></p>
<p class="accessibility">{{ activeWord }}</p>
</div>

<svg id="filters">
<defs>
<filter id="threshold">
<feColorMatrix
in="SourceGraphic"
type="matrix"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 255 -140"
/>
</filter>
</defs>
</svg>
</div>
46 changes: 46 additions & 0 deletions src/lib/ngx-word-morph.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.om-word-morph {
--om-word-morph-font-size: 8rem;

width: fit-content;
position: relative;

.words {
position: relative;
margin: auto;
width: fit-content;
height: fit-content;
top: 0;
bottom: 0;

-webkit-transition: 1s -webkit-filter linear;
-moz-transition: 1s -moz-filter linear;
-moz-transition: 1s filter linear;
-ms-transition: 1s -ms-filter linear;
-o-transition: 1s -o-filter linear;
transition: 1s filter linear, 1s -webkit-filter linear;

p {
margin: 0;
}

.accessibility {
font-size: var(--om-word-morph-font-size);
visibility: hidden;
}

#text1,
#text2 {
position: absolute;
width: 100%;
display: inline-block;
user-select: none;
font-size: var(--om-word-morph-font-size);
}
}

#filters {
position: absolute;
width: 0;
height: 0;
}
}
23 changes: 0 additions & 23 deletions src/lib/ngx-word-morph.component.spec.ts

This file was deleted.

135 changes: 125 additions & 10 deletions src/lib/ngx-word-morph.component.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,131 @@
import { Component } from '@angular/core';
import { CommonModule } from "@angular/common";
import { Component, Input, OnDestroy, OnInit } from "@angular/core";
import { interval, of, repeat, Subject, takeUntil } from "rxjs";

@Component({
selector: 'lib-ngx-word-morph',
selector: "om-word-morph",
standalone: true,
imports: [],
template: `
<p>
ngx-word-morph works!
</p>
`,
styles: ``
imports: [CommonModule],
templateUrl: "./ngx-word-morph.component.html",
styleUrl: "./ngx-word-morph.component.scss",
})
export class NgxWordMorphComponent {
export class NgxWordMorphComponent implements OnInit, OnDestroy {
@Input("styleClass")
styleClass?: string;

@Input("words")
set wordsInput(words: string[]) {
this.words = words;
this.textIndex = this.words.length - 1;
}

@Input("morphDuration")
morphDuration = 1000;

@Input("morphDelay")
morphDelay = 5000;

words!: string[];
activeWord!: string;

private elts!: any;

private fontSize!: number;

private textIndex: number = 0;

ngOnInit(): void {
if (!this.words || this.words.length <= 0) {
throw new Error("om-word-morph: No words were passed to the component!");
}

if (this.words.length === 1) {
this.words = [...this.words, ...this.words];
}

this.elts = {
words: document.getElementById("words") as HTMLElement,
text1: document.getElementById("text1") as HTMLElement,
text2: document.getElementById("text2") as HTMLElement,
};

this.fontSize = parseFloat(
window
.getComputedStyle(this.elts.text1, null)
.getPropertyValue("font-size")
);

this.activeWord = this.words[1];

this.initMorph();
}

destroy$ = new Subject<void>();

ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}

initMorph(): void {
this.elts.text2.style.filter = "";
this.elts.text2.style.opacity = "100%";

this.elts.text1.style.filter = "";
this.elts.text1.style.opacity = "0%";

this.morphText();

interval(this.morphDelay + this.morphDuration)
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
this.morphText();
});
}

private morphText() {
let fraction = 0;

this.elts.words.style.filter = "url(#threshold) blur(0.6px)";

this.elts.text1.textContent =
this.words[this.textIndex % this.words.length];
this.elts.text2.textContent =
this.words[(this.textIndex + 1) % this.words.length];

of([])
.pipe(
repeat({ count: 100, delay: this.morphDuration / 100 }),
takeUntil(this.destroy$)
)
.subscribe(() => {
fraction += 1;
this.setMorph(fraction / 100);

if (fraction === 50) {
this.activeWord =
this.words[(this.textIndex + 1) % this.words.length];
}

if (fraction === 100) {
this.textIndex++;
this.elts.words.style.filter = "";
}
});
}

private setMorph(fraction: number) {
this.elts.text2.style.filter = `blur(${Math.min(
8 / fraction - 8,
this.fontSize
)}px)`;
this.elts.text2.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;

fraction = 1 - fraction;
this.elts.text1.style.filter = `blur(${Math.min(
8 / fraction - 8,
this.fontSize
)}px)`;
this.elts.text1.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;
}
}
16 changes: 0 additions & 16 deletions src/lib/ngx-word-morph.service.spec.ts

This file was deleted.

9 changes: 0 additions & 9 deletions src/lib/ngx-word-morph.service.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
* Public API Surface of ngx-word-morph
*/

export * from './lib/ngx-word-morph.service';
export * from './lib/ngx-word-morph.component';
export * from "./lib/ngx-word-morph.component";

0 comments on commit f76820e

Please sign in to comment.