favoritos
Version:
Favoritos is a JavaScript plugin that adds some HTML5 canvas magic to your favicon. With just a wee bit of code, we can make some really cool effects.
458 lines (369 loc) • 15.1 kB
Markdown
<!-- Favoritos is a JavaScript plugin that adds some HTML5 canvas magic to your favicon. With just a wee bit of code, we can make some really cool effects. -->
<p align="center">
<img width="130" height="120" src="https://raw.githubusercontent.com/webistomin/favoritos/master/assets/logo.svg" alt="Favoritos">
</p>
<h1 align="center">Favoritos</h1>
<h4 align="center">Favoritos is a JavaScript plugin that adds some HTML5 canvas magic to your favicon. With just a wee bit of code, we can make some really cool effects.</h4>
<h5 align="center">⭐️ Star me on GitHub — it helps!</h5>
<p align="center">
<a href="https://github.com/webistomin/favoritos/actions/workflows/ci.yml">
<img src="https://github.com/webistomin/favoritos/actions/workflows/ci.yml/badge.svg"
alt="GitHub Actions">
</a>
<a href="https://codecov.io/gh/webistomin/favoritos">
<img src="https://codecov.io/gh/webistomin/favoritos/branch/master/graph/badge.svg" alt="codecoverage" />
</a>
<a href="https://www.codefactor.io/repository/github/webistomin/favoritos"><img src="https://www.codefactor.io/repository/github/webistomin/favoritos/badge" alt="CodeFactor" /></a>
<img alt="GitHub issues" src="https://img.shields.io/github/issues/webistomin/favoritos">
<img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/webistomin/favoritos">
<img alt="npm type definitions" src="https://img.shields.io/npm/types/favoritos">
<a href="https://bundlephobia.com/result?p=favoritos">
<img alt="npm bundle size" src="https://img.shields.io/bundlephobia/minzip/favoritos">
</a>
</p>
<p align="center">
<a href="https://www.npmjs.com/package/favoritos"><img alt="npm" src="https://img.shields.io/npm/v/favoritos" /></a>
<a href="https://www.npmjs.com/package/favoritos"><img alt="downloads" src="https://img.shields.io/npm/dt/favoritos" /></a>
<a href="https://www.jsdelivr.com/package/npm/favoritos"><img alt="jsdeliver" src="https://img.shields.io/jsdelivr/npm/hy/favoritos?style=rounded"/></a>
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
<img src="https://img.shields.io/badge/all_contributors-1-orange.svg" alt="contributors">
<!-- ALL-CONTRIBUTORS-BADGE:END -->
</p>
<p align="center">
<a href="#key-features-">Key Features</a> •
<a href="#demo-">Demo</a> •
<a href="#installation-">Installation</a> •
<a href="#how-to-use-">How To Use</a> •
<a href="#browsers-support-">Browsers support</a> •
<a href="#license-">License</a> •
<a href="#contributing-">Contributing</a>
</p>
## Key Features ✨
* **Small.** ~ 2.78KB (minified and gzipped). <a href="https://github.com/ai/size-limit">Size Limit</a> controls the size.
* **No dependencies.**
* **Friendly and flexible configuration**
* **Easy to use**
* **Typescript** support
* **SSR friendly**
## Demo 👀
### [DEMO](https://favoritos.vercel.app/)
## Installation 🚀
### Using package managers
#### npm
```shell script
$ npm install favoritos --save
```
#### yarn
```shell script
$ yarn add favoritos
```
### via CDN
Add script right before closing `</body>` tag
```html
<script src="https://unpkg.com/favoritos@1.0.1/dist/favoritos.iife.js"></script>
or
<script src="https://cdn.jsdelivr.net/npm/favoritos@1.0.1/dist/favoritos.iife.js"></script>
```
_Hint:_ for a better performance add [preconnect](https://css-tricks.com/using-relpreconnect-to-establish-network-connections-early-and-increase-performance/) link in the head of your document.
```html
<head>
<!-- for unkpg cdn -->
<link rel="preconnect" href="https://unpkg.com">
<!-- for jsdelivr cdn -->
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<!-- dns-prefetch only for IE11 -->
<!-- <link rel="dns-prefetch" href="https://unpkg.com"> -->
<!-- <link rel="dns-prefetch" href="https://cdn.jsdelivr.net"> -->
</head>
```
## How to use 🤔
### 1. Initialize favoritos
**Option A: Using ES 2015:**
```js
import Favoritos from 'favoritos';
const favoritos = new Favoritos({
icon: {
// Your options
},
badge: {
// Your options
},
debug: {
// Your options
},
});
```
**Option B: Using CommonJS:**
```js
const Favoritos = require('favoritos');
const favoritos = new Favoritos({
icon: {
// Your options
},
badge: {
// Your options
},
debug: {
// Your options
},
});
```
**Option C: Using CDN:**
```js
/* Favoritos is available from global namespace */
const favoritos = new Favoritos({
icon: {
// Your options
},
badge: {
// Your options
},
debug: {
// Your options
},
});
```
### 2. Add magic to your favicon
#### Options
#### Icon options
<table>
<thead>
<tr>
<th>Option</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>iconSelector</code></td>
<td><code>'link[rel*="icon"]'</code></td>
<td>A selector for your favicon where magic will be drawn.</td>
</tr>
<tr>
<td><code>backgroundColor</code></td>
<td><code>'#d21f3c'</code></td>
<td>Background color for the icon. Used when rendering the progress bar. May be a string or an array. If an array is passed, a gradient will be drawn.
</td>
</tr>
<tr>
<td><code>shape</code></td>
<td><code>'circle'</code></td>
<td>The shape for the icon. Can take the following values: <code>circle</code>, <code>rect</code>.
</td>
</tr>
<tr>
<td><code>lineWidth</code></td>
<td><code>4</code></td>
<td>Line width for your icon.</td>
</tr>
<tr>
<td><code>width</code></td>
<td><code>32</code></td>
<td>Width for your icon. Initially, there is the width of a standard favicon.
</td>
</tr>
<tr>
<td><code>height</code></td>
<td><code>32</code></td>
<td>Height for your icon. Initially, there is the height of a standard favicon.
</td>
</tr>
</tbody>
</table>
#### Badge options
<table>
<thead>
<tr>
<th>Option</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>fontSize</code></td>
<td><code>18</code></td>
<td>Font size of badge text.</td>
</tr>
<tr>
<td><code>backgroundColor</code></td>
<td><code>'#d21f3c'</code></td>
<td>Background color for the badge.</td>
</tr>
<tr>
<td><code>fontFamily</code></td>
<td><code>'Helvetica, Arial, sans-serif'</code></td>
<td>Font family for the badge text.</td>
</tr>
<tr>
<td><code>shape</code></td>
<td><code>'circle'</code></td>
<td>The shape for the icon. Can take the following values: <code>circle</code>, <code>rect</code>.
</td>
</tr>
<tr>
<td><code>position</code></td>
<td><code>'bottom-right'</code></td>
<td>Position for your badge. Can take the following values: <code>top-left</code>, <code>top-right</code>, <code>bottom-left</code>, <code>bottom-right</code>.
</td>
</tr>
<tr>
<td><code>minWidth</code></td>
<td><code>22</code></td>
<td>Minimal width for your badge.</td>
</tr>
<tr>
<td><code>minHeight</code></td>
<td><code>22</code></td>
<td>Minimal height for your icon.</td>
</tr>
</tbody>
</table>
#### Debug options
_Debug mode can be useful if you want to look at the favicon near_
<table>
<thead>
<tr>
<th>Option</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>enabled</code></td>
<td><code>false</code></td>
<td>Turns debugging on and off.</td>
</tr>
<tr>
<td><code>debugSelector</code></td>
<td><code>'#favoritos-debug'</code></td>
<td>Element selector where the canvas will be drawn.</td>
</tr>
</tbody>
</table>
## 3. Call methods
**favoritos.drawBadge()**
```js
favoritos.drawBadge('')
favoritos.drawBadge(1)
favoritos.drawBadge(123)
```
Draws a badge on top of the favicon. With an empty string – an empty badge will be drawn. You can also pass numbers.
---
**favoritos.drawImage()**
```js
/* Image example */
const img = document.querySelector('.my-image');
favoritos.drawImage(img)
/* Video example */
const video = document.querySelector('.my-video');
video.addEventListener('play', function () {
function step() {
favoritos.drawImage(video)
requestAnimationFrame(step)
}
requestAnimationFrame(step);
})
```
Draws a picture or video instead of your favicon. Takes one argument - the content to be drawn. Image or video **must have** `crossorigin="anonymous"` attribute
---
**favoritos.drawProgress()**
```js
/* Scroll progress example */
document.addEventListener('scroll', () => {
const root = document.documentElement;
const scrollTopInPx = root.scrollTop;
const pageHeightInPx = root.scrollHeight - root.clientHeight;
const scrollPercent = (scrollTopInPx / pageHeightInPx) * 100;
const scrollPercentRounded = Math.round(scrollPercent);
favoritos.drawProgressBar(scrollPercentRounded);
})
/* XHR example */
const formData = new FormData();
formData.append('files', /* Your data */);
const xhr = new XMLHttpRequest();
xhr.open('POST', '');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const complete = (event.loaded / event.total * 100 | 0);
favoritos.drawProgressBar(complete);
}
});
xhr.send(formData);
```
Allows you to draw a progress bar instead of your icon. The progress bar shape depends on the option <code>shape</code> passed during library initialization.
The method takes two arguments: <code>progress</code> and <code>useFavicon</code>. <code>progress</code> indicates how much has already been completed. Value from 0 to 100. <code>useFavicon</code> indicates whether to draw the progress bar on top of the favicon.
---
**favoritos.setOptions()**
```js
/* For example, set icon background color to green if task was done */
favoritos.setOptions({
icon: {
backgroundColor: 'green'
}
})
```
You can change any options for the library. But after the change, you must definitely call the icon renderer with the method of which you use (<code>drawBadge()</code> or <code>drawProgress()</code>).
---
**favoritos.setIcon()**
```js
/* Change favicon on tab change */
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
document.title = 'Hello again! 😀';
favoritos.setIcon('./on-visible.png')
} else {
document.title = 'I miss you! 😭';
favoritos.setIcon('./on-visible.png')
}
})
/* Change favicon on theme change */
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
const newColorScheme = event.matches ? "dark" : "light";
if (newColorScheme === 'dark') {
favoritos.setIcon('./dark-favicon.png')
} else {
favoritos.setIcon('./light-favicon.png')
}
});
```
Simply draws a new favicon.
---
**favoritos.reset()**
```js
favoritos.reset();
```
Resets the library to its original state. Draws your default favicon.
---
## Browsers 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/)<br/>IE / Edge | [<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/)<br/>Firefox | [<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/)<br/>Chrome | [<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/)<br/>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Opera | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/yandex/yandex_48x48.png" alt="Yandex" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Yandex |
| --------- | --------- | --------- | --------- | --------- | --------- | --------- |
| IE11*, Edge 12+| 40+ | 42+ | 10.1+| 10.3+ | 29+| 15.6+
`*` – For IE11 you need to install **Object.assign** polyfill. Also IE11 cannot render base64 icons, so the <code>setIcon</code> method only works there.
If you want to send a polyfill only to browsers that need it, there's a handy service called [Polyfill.io](https://polyfill.io/v3/url-builder/) which does just that, it offers a wide array of polyfills.
Here's an example of using [polyfill.io](https://polyfill.io/v3/url-builder/) to polyfill only the `Object.assign` feature, so if we put this right before closing `</body>` tag of `index.html` and `Favoritos` script, Polyfill.io will read the user agent and use that information to determine if the browser requires a polyfill for the feature or features listed. Since I'm using Chrome it will send back an empty response since my browser doesn't need it, pretty slick.
```html
<script src="https://polyfill.io/v3/polyfill.min.js?features=Object.assign"></script>
```
## License 📄
### [MIT](https://github.com/webistomin/favoritos/blob/master/LICENSE)
## Contributing 🎉
Found a bug? Missing a specific feature?
Your contributions are always welcome! Please have a look at the [contribution guidelines](https://github.com/webistomin/favoritos/blob/master/CONTRIBUTING.md) first.
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://github.com/webistomin"><img src="https://avatars0.githubusercontent.com/u/30475699?v=4" width="100px;" alt=""/><br /><sub><b>Alexey Istomin</b></sub></a><br /><a href="#infra-webistomin" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/webistomin/favoritos/commits?author=webistomin" title="Code">💻</a> <a href="#ideas-webistomin" title="Ideas, Planning, & Feedback">🤔</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!