creepyface
Advanced tools
Comparing version 7.2.1 to 7.2.2-alpha.0
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).creepyface=e()}(this,function(){"use strict";var i=function(o){return 1===o.length?o[0]:function(e,n){var t=o.map(function(t){return t(e,n)});return function(){return t.forEach(function(t){return t()})}}},t=function(n){var o,r=[];return function(t,e){return r.push(t),1===r.length&&(o=n(function(e){return r.forEach(function(t){return t(e)})},e)),function(){r.splice(r.indexOf(t),1),0===r.length&&o&&o()}}},e=t(function(e){var t=function(t){return e([t.clientX,t.clientY])};return window.addEventListener("mousemove",t,!0),function(){return window.removeEventListener("mousemove",t,!0)}}),s=function(t,e){return[t[0]+e[0],t[1]+e[1]]},d=function(t){return t*Math.PI/180},h=function(t){return e=Math.atan2(t[1],t[0]),n=2*Math.PI,180*((n+e%n)%n)/Math.PI;var e,n},n=t(function(r){var t=function(t){for(var e=[0,0],n=0;n<t.touches.length;n++){var o=t.touches[n];e=s(e,[o.clientX,o.clientY])}r(e)};return window.addEventListener("touchmove",t,!0),function(){return window.removeEventListener("touchmove",t,!0)}}),o={mouse:e,finger:n,pointer:i([e,n])},c=function(t){return o[t]?o[t]:(console.error("No point provider registered as '".concat(t,"', defaulting to pointer.")),o.pointer)},r=function(t){var e=t?parseFloat(t):NaN;return isNaN(e)?void 0:e},u=function(t){return{hover:t.getAttribute("data-src-hover")||void 0,looks:function(t){for(var e=/data-src-look-(\d+)/i,n=[],o=0;o<t.attributes.length;o++){var r=t.attributes[o],i=e.exec(r.name);i&&n.push({angle:parseFloat(i[1]),src:r.value})}return n.length?n:void 0}(t),points:t.getAttribute("data-points")||void 0,timeToDefault:r(t.getAttribute("data-timetodefault")),throttle:r(t.getAttribute("data-throttle"))}},a=function(){};function f(t){var e,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},o=function(r){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{},e=Object.keys(i);"function"==typeof Object.getOwnPropertySymbols&&(e=e.concat(Object.getOwnPropertySymbols(i).filter(function(t){return Object.getOwnPropertyDescriptor(i,t).enumerable}))),e.forEach(function(t){var e,n,o;e=r,o=i[n=t],n in e?Object.defineProperty(e,n,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[n]=o})}return r}({},u(t),n),r=t.getAttribute("src");if(!r)throw new Error("A default URL must be specified");return{src:r,hover:o.hover||"",pointProvider:(e=o,"function"==typeof e.points?e.points:i((e.points||"pointer").split(",").map(c))),looks:o.looks||[],timeToDefault:void 0!==o.timeToDefault?o.timeToDefault:1e3,throttle:o.throttle||100,onDebug:o.onDebug||a,onAttach:o.onAttach||a,onDetach:o.onDetach||a}}var l=function(r,i){var c=[];r.forEach(function(t){var e,n,o;e=t,n=function(t){c.push(t),c.length===r.length&&i(c)},(o=new Image).src=e,o.onload=o.onerror=function(){o.naturalWidth||console.error("Creepyface was unable to load ".concat(e)),delete o.onload,delete o.onerror,n(o)}})};function v(r,i,c,u){var a,f=!1,l=0;function s(){a&&clearTimeout(a)}function t(){var t=this,e=Date.now()-l,n=arguments;function o(){l=Date.now(),c.apply(t,n)}f||(u&&!a&&o(),s(),void 0===u&&r<e?o():!0!==i&&(a=setTimeout(u?function(){a=void 0}:o,void 0===u?r-e:r)))}return"boolean"!=typeof i&&(u=c,c=i,i=void 0),t.cancel=function(){s(),f=!0},t}var p=function(t,e){return h((r=s([window.scrollX,window.scrollY],e),c=t.getBoundingClientRect(),u=c.left,a=c.top,f=c.width,l=c.height,i=[u+window.pageXOffset+f/2,a+window.pageYOffset+l/2],n=[r[0]-i[0],r[1]-i[1]],o=90,[n[0]*Math.cos(d(o))-n[1]*Math.sin(d(o)),n[0]*Math.sin(d(o))+n[1]*Math.cos(d(o))]));var n,o,r,i,c,u,a,f,l},g=function(t){return 180<Math.abs(t)?t-360*(t<0?-1:1):t},m=function(t,e){return e.slice(0).sort((n=t,function(t,e){return Math.abs(g(t.angle-n))-Math.abs(g(e.angle-n))}))[0];var n},b=function(t,e,n){return e<=t&&t<=n},w=function(t,e){return document.elementFromPoint?document.elementFromPoint(e[0],e[1])===t:(n=t.getBoundingClientRect(),o=[e[0],e[1]],r=n.left,i=n.top,c=n.right,u=n.bottom,b(o[0],r,c)&&b(o[1],i,u));var n,o,r,i,c,u},y=function(s,t){var n,o,e,r,i,c,d=f(s,t);return s.__creepyfaceCancel=(n=s,i=!(o=function(){var t,e,n,f=function(t,e,n){s.src=t,d.onDebug({src:t,point:e,angle:n,options:d})},l=(t=d.timeToDefault,e=function(){return f(d.src)},void 0===n?v(t,e,!1):v(t,n,!1!==e)),o=v(d.throttle,function(t){if(!t)return f(d.src);var e,n,o,r,i,c,u=p(s,t),a=(e=s,n=t,o=u,i=(r=d).looks,(c=r.hover)&&w(e,n)?c:0===i.length?r.src:m(o,i).src);f(a,t,u),0<d.timeToDefault&&l()}),r=d.pointProvider(o,s);return d.onAttach(),function(){l.cancel(),o.cancel(),r(),s.src=d.src,delete s.__creepyfaceCancel,d.onDetach()}}),c=function(){i=!0},l(((r=(e=d).looks.map(function(t){return t.src})).push(e.src),e.hover&&r.push(e.hover),r),function(t){n.__creepyfaceReachableImages=t;var e=o();c=function(){e(),delete n.__creepyfaceReachableImages},(i||t.some(function(t){return!t.naturalWidth}))&&c()}),function(){return c()})};return y.cancel=function(t){var e=t.__creepyfaceCancel;e&&e()},y.registerPointProvider=function(t,e){o[t]=e},document.addEventListener("DOMContentLoaded",function(){for(var t=document.querySelectorAll("img[data-creepy],img[data-creepyface]"),e=0;e<t.length;e++)y(t[e])}),y}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).creepyface=e()}(this,function(){"use strict";function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function c(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n,r;e=o,r=i[n=t],n in e?Object.defineProperty(e,n,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[n]=r}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function u(r){return 1===r.length?r[0]:function(e,n){var t=r.map(function(t){return t(e,n)});return function(){return t.forEach(function(t){return t()})}}}function t(n){var r,o=[];return function(t,e){return o.push(t),1===o.length&&(r=n(function(e){return o.forEach(function(t){return t(e)})},e)),function(){o.splice(o.indexOf(t),1),0===o.length&&r&&r()}}}function s(t,e){return[t[0]+e[0],t[1]+e[1]]}function d(t){return t*Math.PI/180}function h(t){return e=Math.atan2(t[1],t[0]),180*(((n=2*Math.PI)+e%n)%n)/Math.PI;var e,n}function a(t){return i[t]?i[t]:(console.error("No point provider registered as '".concat(t,"', defaulting to pointer.")),i.pointer)}function n(t){var e=t?parseFloat(t):NaN;return isNaN(e)?void 0:e}function f(t){return{hover:t.getAttribute("data-src-hover")||void 0,looks:function(t){for(var e=/data-src-look-(\d+)/i,n=[],r=0;r<t.attributes.length;r++){var o=t.attributes[r],i=e.exec(o.name);i&&n.push({angle:parseFloat(i[1]),src:o.value})}return n.length?n:void 0}(t),points:t.getAttribute("data-points")||void 0,timeToDefault:n(t.getAttribute("data-timetodefault")),throttle:n(t.getAttribute("data-throttle"))}}function l(){}var r=t(function(e){function t(t){return e([t.clientX,t.clientY])}return window.addEventListener("mousemove",t,!0),function(){return window.removeEventListener("mousemove",t,!0)}}),o=t(function(o){function t(t){for(var e=[0,0],n=0;n<t.touches.length;n++){var r=t.touches[n];e=s(e,[r.clientX,r.clientY])}o(e)}return window.addEventListener("touchmove",t,!0),function(){return window.removeEventListener("touchmove",t,!0)}}),i={mouse:r,finger:o,pointer:u([r,o])};function p(t,e){var n,r=1<arguments.length&&void 0!==e?e:{},o=c({},f(t),{},r),i=t.getAttribute("src");if(!i)throw new Error("A default URL must be specified");return{src:i,hover:o.hover||"",pointProvider:"function"==typeof(n=o).points?n.points:u((n.points||"pointer").split(",").map(a)),looks:o.looks||[],timeToDefault:void 0!==o.timeToDefault?o.timeToDefault:1e3,throttle:o.throttle||100,onDebug:o.onDebug||l,onAttach:o.onAttach||l,onDetach:o.onDetach||l}}function v(o,i){var c=[];o.forEach(function(t){var e,n,r;e=t,n=function(t){c.push(t),c.length===o.length&&i(c)},(r=new Image).src=e,r.onload=r.onerror=function(){r.naturalWidth||console.error("Creepyface was unable to load ".concat(e)),delete r.onload,delete r.onerror,n(r)}})}function g(o,i,c,u){var a,f=!1,l=0;function s(){a&&clearTimeout(a)}function t(){var t=this,e=Date.now()-l,n=arguments;function r(){l=Date.now(),c.apply(t,n)}f||(u&&!a&&r(),s(),void 0===u&&o<e?r():!0!==i&&(a=setTimeout(u?function(){a=void 0}:r,void 0===u?o-e:o)))}return"boolean"!=typeof i&&(u=c,c=i,i=void 0),t.cancel=function(){s(),f=!0},t}function m(t,e){return h((o=s([window.scrollX,window.scrollY],e),c=t.getBoundingClientRect(),u=c.left,a=c.top,f=c.width,l=c.height,i=[u+window.pageXOffset+f/2,a+window.pageYOffset+l/2],n=[o[0]-i[0],o[1]-i[1]],r=90,[n[0]*Math.cos(d(r))-n[1]*Math.sin(d(r)),n[0]*Math.sin(d(r))+n[1]*Math.cos(d(r))]));var n,r,o,i,c,u,a,f,l}function b(t){return 180<Math.abs(t)?t-360*(t<0?-1:1):t}function w(t,e){return e.slice(0).sort((n=t,function(t,e){return Math.abs(b(t.angle-n))-Math.abs(b(e.angle-n))}))[0];var n}function y(t,e,n){return e<=t&&t<=n}function O(t,e){return document.elementFromPoint?document.elementFromPoint(e[0],e[1])===t:(n=t.getBoundingClientRect(),r=[e[0],e[1]],o=n.left,i=n.top,c=n.right,u=n.bottom,y(r[0],o,c)&&y(r[1],i,u));var n,r,o,i,c,u}function D(s,t){var n,r,e,o,i,c,d=p(s,t);return s.__creepyfaceCancel=(n=s,i=!(r=function(){function f(t,e,n){s.src=t,d.onDebug({src:t,point:e,angle:n,options:d})}var t,e,n,l=(t=d.timeToDefault,e=function(){return f(d.src)},void 0===n?g(t,e,!1):g(t,n,!1!==e)),r=g(d.throttle,function(t){if(!t)return f(d.src);var e,n,r,o,i,c,u=m(s,t),a=(e=s,n=t,r=u,i=(o=d).looks,(c=o.hover)&&O(e,n)?c:0===i.length?o.src:w(r,i).src);f(a,t,u),0<d.timeToDefault&&l()}),o=d.pointProvider(r,s);return d.onAttach(),function(){l.cancel(),r.cancel(),o(),s.src=d.src,delete s.__creepyfaceCancel,d.onDetach()}}),c=function(){i=!0},v(((o=(e=d).looks.map(function(t){return t.src})).push(e.src),e.hover&&o.push(e.hover),o),function(t){n.__creepyfaceReachableImages=t;var e=r();c=function(){e(),delete n.__creepyfaceReachableImages},(i||t.some(function(t){return!t.naturalWidth}))&&c()}),function(){return c()})}return D.cancel=function(t){var e=t.__creepyfaceCancel;e&&e()},D.registerPointProvider=function(t,e){i[t]=e},document.addEventListener("DOMContentLoaded",function(){for(var t=document.querySelectorAll("img[data-creepy],img[data-creepyface]"),e=0;e<t.length;e++)D(t[e])}),D}); | ||
//# sourceMappingURL=creepyface.umd.js.map |
{ | ||
"name": "creepyface", | ||
"version": "7.2.1", | ||
"version": "7.2.2-alpha.0", | ||
"keywords": [ | ||
@@ -34,7 +34,4 @@ "face", | ||
"geckodriver": "^1.19.1", | ||
"husky": "^1.3.1", | ||
"jest": "^24.9.0", | ||
"lint-staged": "^8.1.0", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^1.15.3", | ||
"rimraf": "^2.6.3", | ||
@@ -58,8 +55,2 @@ "rollup": "^1.0.0", | ||
}, | ||
"lint-staged": { | ||
"./**/*": [ | ||
"prettier --write", | ||
"git add" | ||
] | ||
}, | ||
"scripts": { | ||
@@ -75,11 +66,3 @@ "all": "run-s clean lint build test", | ||
}, | ||
"prettier": { | ||
"semi": false, | ||
"singleQuote": true | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
} | ||
"gitHead": "0b8bf3b500849bc2717256723f1e0b4396dbf8c0" | ||
} |
215
README.md
@@ -1,217 +0,8 @@ | ||
# [Creepyface](https://creepyface.io) · [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/4lejandrito/creepyface/blob/master/LICENSE) [![npm version](https://img.shields.io/npm/v/creepyface.svg?style=flat)](https://www.npmjs.com/package/creepyface) [![Build](https://github.com/4lejandrito/creepyface/workflows/Build/badge.svg)](https://github.com/4lejandrito/creepyface/actions?query=workflow%3ABuild+branch%3Amaster) [![Coverage Status](https://coveralls.io/repos/github/4lejandrito/creepyface/badge.svg?branch=master)](https://coveralls.io/github/4lejandrito/creepyface?branch=master) | ||
# [Creepyface](https://creepyface.io) · [![npm version](https://img.shields.io/npm/v/creepyface.svg?style=flat)](https://www.npmjs.com/package/creepyface) | ||
Creepyface is a little JavaScript tool that makes your face look at the pointer (or a [firefly](https://github.com/4lejandrito/creepyface-firefly)). It is ideal for resumes, team presentation sites, etc... | ||
This is the core library. The documentation is in the [root README](../../README.md). | ||
[Codepen](https://codepen.io/4lejandrito/pen/vbgxEB) | ||
![Example animated gif of a face looking at the pointer](example.gif) | ||
Creepyface in the wild: | ||
- https://atroshenkonikita.com | ||
- https://www.yitzi.dev | ||
- https://1aville.ch/about.html | ||
- https://github.com/reflog/mattermost-plugin-creepy | ||
Now also available for React: https://github.com/4lejandrito/react-creepyface. | ||
## Usage | ||
The simplest way to create your Creepyface is by using [our wizard](https://creepyface.io/create). | ||
--- | ||
If you want to customize it even more you can use our declarative data-attribute API: | ||
1. Take a bunch of pictures of yourself looking at different directions. | ||
2. Create a standard `<img>` tag like the following using the pictures you just took: | ||
```html | ||
<img | ||
data-creepyface | ||
src="img/face/serious.jpg" | ||
data-src-hover="img/face/crazy.jpg" | ||
data-src-look-0="img/face/north.jpg" | ||
data-src-look-45="img/face/north-east.jpg" | ||
data-src-look-90="img/face/east.jpg" | ||
data-src-look-135="img/face/south-east.jpg" | ||
data-src-look-180="img/face/south.jpg" | ||
data-src-look-225="img/face/south-west.jpg" | ||
data-src-look-270="img/face/west.jpg" | ||
data-src-look-315="img/face/north-west.jpg" | ||
/> | ||
``` | ||
The `data-src-look` attributes must be set to degrees (0 - 360). | ||
3. Include Creepyface script in your page: | ||
```html | ||
<script src="https://creepyface.io/creepyface.js"></script> | ||
``` | ||
Creepyface will automatically detect your image (thanks to the `data-creepyface` attribute) and make it look at the mouse or fingers depending on which device you are using. | ||
You can add as many Creepyfaces as you want as long as they all have the `data-creepyface` attribute. | ||
If you want to stop Creepyface on a given image: | ||
```js | ||
creepyface.cancel(document.querySelector('img')) | ||
``` | ||
### Full list of data attributes | ||
| Name | Description | | ||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `data-creepyface` | Add this to automatically attach creepyface to your image when the page loads. | | ||
| `data-src-hover` | The URL of the image to use when the pointer is over your image. | | ||
| `data-src-look-<angle>` | The URL of the image to use when the pointer forms the specified angle (in degrees) with the center of your image. Add as many as you want. | | ||
| `data-timetodefault` | The amount of time (in milliseconds) after which the default src is restored if no pointer events are received. 1 second by default. 0 means it will never be restored (the image will always look at the pointer). | | ||
| `data-throttle` | The amount of time (in milliseconds) to wait between src changes. 100 by default. | | ||
| `data-points` | Optionally, a comma-separated list of point provider names to make your face look at things other than the pointer. See [Super advanced usage](#super-advanced-usage) for more information. | | ||
## Advanced usage | ||
For more advanced use cases Creepyface can also be set up via a programmatic API: | ||
```js | ||
import creepyface from 'creepyface' | ||
const img = document.querySelector('img#face') | ||
const cancel = creepyface(img, { | ||
// Time (in ms) to wait between src updates | ||
throttle: 100, | ||
// Image URL to display on hover | ||
hover: 'img/face/crazy.jpg', | ||
// Each of the images looking at a given direction | ||
looks: [ | ||
{ angle: 0, src: 'img/face/north.jpg' }, | ||
{ angle: 45, src: 'img/face/north-east.jpg' }, | ||
{ angle: 90, src: 'img/face/east.jpg' }, | ||
{ angle: 135, src: 'img/face/south-east.jpg' }, | ||
{ angle: 180, src: 'img/face/south.jpg' }, | ||
{ angle: 225, src: 'img/face/south-west.jpg' }, | ||
{ angle: 270, src: 'img/face/west.jpg' }, | ||
{ angle: 315, src: 'img/face/north-west.jpg' } | ||
], | ||
// Time (in ms) to restore the default image after the last input | ||
timeToDefault: 1000 | ||
}) | ||
// at some point restore the original image and stop creepyface | ||
cancel() | ||
``` | ||
## Super advanced usage | ||
Creepyface will look at the pointer by default, however custom point providers can be defined. | ||
For example, to make your face look at a random point every half a second (see [codepen](https://codepen.io/4lejandrito/pen/ZEYJLrN)) you need to register a [point provider](https://github.com/4lejandrito/creepyface/blob/master/src/types.d.ts#L5-L8): | ||
```js | ||
import creepyface from 'creepyface' | ||
creepyface.registerPointProvider('random', (consumer, img) => { | ||
const interval = setInterval( | ||
() => | ||
consumer([ | ||
Math.random() * window.innerWidth, | ||
Math.random() * window.innerHeight | ||
]), | ||
500 | ||
) | ||
return () => { | ||
clearInterval(interval) | ||
} | ||
}) | ||
``` | ||
and consume it using the `data-points` attribute: | ||
```html | ||
<img | ||
data-creepyface | ||
data-points="random" | ||
src="img/face/serious.jpg" | ||
data-src-hover="img/face/crazy.jpg" | ||
data-src-look-0="img/face/north.jpg" | ||
data-src-look-45="img/face/north-east.jpg" | ||
data-src-look-90="img/face/east.jpg" | ||
data-src-look-135="img/face/south-east.jpg" | ||
data-src-look-180="img/face/south.jpg" | ||
data-src-look-225="img/face/south-west.jpg" | ||
data-src-look-270="img/face/west.jpg" | ||
data-src-look-315="img/face/north-west.jpg" | ||
/> | ||
``` | ||
or pass it programmatically: | ||
```js | ||
const img = document.querySelector('img#face') | ||
creepyface(img, { | ||
// Provides the points to look at | ||
points: (consumer, img) => { | ||
const interval = setInterval( | ||
() => | ||
consumer([ | ||
Math.random() * window.innerWidth, | ||
Math.random() * window.innerHeight | ||
]), | ||
500 | ||
) | ||
return () => { | ||
clearInterval(interval) | ||
} | ||
}, | ||
// Image URL to display on hover | ||
hover: 'img/face/crazy.jpg', | ||
// Each of the images looking at a given direction | ||
looks: [ | ||
{ angle: 0, src: 'img/face/north.jpg' }, | ||
{ angle: 45, src: 'img/face/north-east.jpg' }, | ||
{ angle: 90, src: 'img/face/east.jpg' }, | ||
{ angle: 135, src: 'img/face/south-east.jpg' }, | ||
{ angle: 180, src: 'img/face/south.jpg' }, | ||
{ angle: 225, src: 'img/face/south-west.jpg' }, | ||
{ angle: 270, src: 'img/face/west.jpg' }, | ||
{ angle: 315, src: 'img/face/north-west.jpg' } | ||
] | ||
}) | ||
``` | ||
**Note:** several point providers can work at the same time by using a comma-separated string like `"random,pointer"`. | ||
The following point providers are available out of the box: | ||
- `pointer` for both mouse and touch events. This is the default. | ||
- `mouse` just for mouse events. | ||
- `finger` just for touch events. | ||
The are also external point providers: | ||
- [firefly](https://github.com/4lejandrito/creepyface-firefly) to follow a moving firefly on the screen. | ||
## Developing | ||
- `npm start` will spin up a local server with the sample page watching your file changes. | ||
- `npm test` will run the tests. | ||
- `npm start` will spin up a test page. | ||
- `npm run build` will generate the production scripts under the `dist` folder. | ||
## Contributing | ||
Please feel free to create issues and / or submit pull requests. For the latter, [test cases](test/) are very welcome. | ||
## License | ||
MIT, see [LICENSE](https://github.com/4lejandrito/creepyface/blob/master/LICENSE) for details. | ||
## Big Thanks | ||
Cross-browser Testing Platform and Open Source ❤️ provided by [Sauce Labs][homepage]. | ||
[homepage]: https://saucelabs.com |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28
33450
2
9