diff --git a/README.md b/README.md
index 57255f8..b8b942c 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ A dependency free script that let elements follow your cursor without a huge ove
## Usage
1. Include the `follow.min.js` script to your project
2. Add the `data-follow` attribute to the `position: absolute` elements which you want to follow the cursor
-3. Set the factor on how big they should follow like so `data-follow="100"` (higher equals more movement, if you
+3. Set the factor on how big they should follow like so `data-follow="100"` (higher equals less movement, if you
leave it empty, it is set to 10.
## Include Script
@@ -13,7 +13,7 @@ leave it empty, it is set to 10.
2. ``
### unpkg
-1. ``
+1. ``
## Options
### Dynamically add new elements
@@ -35,4 +35,4 @@ In the current state, the script wont work properly with a transition on the ele
Have a look in the `examples` folder to see some magic.
## Contribute
-Feel free to open a Pullrequest or create a Issue on this project.
\ No newline at end of file
+Feel free to open a Pull request or create a Issue on this project.
\ No newline at end of file
diff --git a/dist/follow.min.js b/dist/follow.min.js
index 384cafe..3321af9 100644
--- a/dist/follow.min.js
+++ b/dist/follow.min.js
@@ -1 +1 @@
-!function(t){var o={};function e(l){if(o[l])return o[l].exports;var r=o[l]={i:l,l:!1,exports:{}};return t[l].call(r.exports,r,r.exports,e),r.l=!0,r.exports}e.m=t,e.c=o,e.d=function(t,o,l){e.o(t,o)||Object.defineProperty(t,o,{enumerable:!0,get:l})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,o){if(1&o&&(t=e(t)),8&o)return t;if(4&o&&"object"==typeof t&&t&&t.__esModule)return t;var l=Object.create(null);if(e.r(l),Object.defineProperty(l,"default",{enumerable:!0,value:t}),2&o&&"string"!=typeof t)for(var r in t)e.d(l,r,function(o){return t[o]}.bind(null,r));return l},e.n=function(t){var o=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(o,"a",o),o},e.o=function(t,o){return Object.prototype.hasOwnProperty.call(t,o)},e.p="",e(e.s=0)}([function(t,o){window.follow={debug:!1,elements:[],attribute:"data-follow",defaultFactor:10,init:void 0,animate:void 0,log:void 0},follow.init=()=>{let t=document.querySelectorAll(`[${follow.attribute}]`);follow.log("targets",t);for(let o of t){let t={factor:o.getAttribute(follow.attribute)?o.getAttribute(follow.attribute):follow.defaultFactor,target:o,x:0,y:0,startPosition:{x:0,y:0}};t.startPosition.x=t.target.offsetLeft,t.startPosition.y=t.target.offsetTop,follow.elements.push(t)}follow.log("elements",follow.elements)},follow.animate=t=>{let o=t.clientX,e=t.clientY;follow.log("mouseX",o),follow.log("mouseY",e);for(let t of follow.elements){follow.log("element",t),t.x=t.target.offsetLeft,t.y=t.target.offsetTop;let l=(o-t.x)/t.factor,r=(e-t.y)/t.factor;follow.log("future position x",l),follow.log("future position y",r),t.target.style.left=t.startPosition.x+l+"px",t.target.style.top=t.startPosition.y+r+"px"}},follow.log=(t,o)=>{follow.debug&&(o?console.log(t,o):console.log(t))},follow.init(),document.addEventListener("mousemove",follow.animate)}]);
\ No newline at end of file
+!function(t){var e={};function o(i){if(e[i])return e[i].exports;var n=e[i]={i:i,l:!1,exports:{}};return t[i].call(n.exports,n,n.exports,o),n.l=!0,n.exports}o.m=t,o.c=e,o.d=function(t,e,i){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(o.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)o.d(i,n,function(e){return t[e]}.bind(null,n));return i},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=0)}([function(t,e,o){"use strict";function i(t,e,o="red",i=3e3){if(follow.debug.dot){let n=document.createElement("i");n.style.position="absolute",n.style.height="1px",n.style.width="1px",n.style.backgroundColor=o,n.style.zIndex="100",n.style.left=t+"px",n.style.top=e+"px",document.body.append(n),setTimeout(()=>{n.remove()},i)}}function n(t,e){follow.debug.log&&(e?console.log(t,e):console.log(t))}o.r(e),window.follow={debug:{log:!1,dot:!1},elements:[],attribute:"data-follow",defaultFactor:10,init:void 0,animate:void 0},follow.init=()=>{let t=document.querySelectorAll(`[${follow.attribute}]`);n("targets",t);for(let e of t){let t={factor:e.getAttribute(follow.attribute)?e.getAttribute(follow.attribute):follow.defaultFactor,target:e,x:0,y:0,dimensions:{height:0,width:0},initialPosition:{x:0,y:0}};t.dimensions.height=t.target.offsetHeight,t.dimensions.width=t.target.offsetWidth,t.initialPosition.x=t.target.offsetLeft+t.dimensions.width/2,t.initialPosition.y=t.target.offsetTop+t.dimensions.height/2,i(t.initialPosition.x,t.initialPosition.y,"red",1e4),follow.elements.push(t)}n("elements",follow.elements)},follow.animate=t=>{let e=t.clientX,o=t.clientY;-1!==navigator.userAgent.search("Firefox")&&(e+=9,o+=15),i&&i(e,o,"blue"),n("mouseX",e),n("mouseY",o);for(let t of follow.elements){n("element",t);let l=(e-t.initialPosition.x)/t.factor,r=(o-t.initialPosition.y)/t.factor,s=t.initialPosition.x+l-t.dimensions.width/2,f=t.initialPosition.y+r-t.dimensions.height/2;t.target.style.left=s+"px",t.target.style.top=f+"px",i&&i(s,f,"green"),n("future position x",s),n("future position y",f)}},follow.init(),document.addEventListener("mousemove",follow.animate)}]);
\ No newline at end of file
diff --git a/examples/basic.html b/examples/basic.html
index 7ec84ab..3d5aa92 100644
--- a/examples/basic.html
+++ b/examples/basic.html
@@ -1,35 +1,35 @@
-
- Basic Example - index.js
+
+ Basic Example - follow.js
-
+ div:nth-child(3) {
+ top: 30%;
+ left: 100px;
+ background: yellow;
+ }
+
diff --git a/examples/exact.html b/examples/exact.html
new file mode 100644
index 0000000..d62256b
--- /dev/null
+++ b/examples/exact.html
@@ -0,0 +1,40 @@
+
+
+
+
+ Exact Example - follow.js
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/helper.js b/src/helper.js
new file mode 100644
index 0000000..a489f2f
--- /dev/null
+++ b/src/helper.js
@@ -0,0 +1,30 @@
+// adds a dot to the given position if enabled
+export function dot (x, y, color = 'red', timeout = 3000) {
+ if (follow.debug.dot) {
+ let dot = document.createElement('i')
+ dot.style.position = 'absolute'
+ dot.style.height = '1px'
+ dot.style.width = '1px'
+ dot.style.backgroundColor = color
+ dot.style.zIndex = '100'
+ dot.style.left = x + 'px'
+ dot.style.top = y + 'px'
+ document.body.append(dot)
+
+ // because of performance issues remove the dot after the timeout
+ setTimeout(() => {
+ dot.remove()
+ }, timeout)
+ }
+}
+
+// log if enabled
+export function log (string, object = undefined) {
+ if (follow.debug.log) {
+ if (object) {
+ console.log(string, object)
+ } else {
+ console.log(string)
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 913ab9c..648e495 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,87 +1,104 @@
+import * as helper from './helper'
+
window.follow = {
- debug: false,
- elements: [],
- attribute: 'data-follow',
- defaultFactor: 10,
- init: undefined,
- animate: undefined,
- log: undefined
+ debug: {
+ log: false,
+ dot: false
+ },
+ elements: [],
+ attribute: 'data-follow',
+ defaultFactor: 10,
+ init: undefined,
+ animate: undefined
}
follow.init = () => {
- // get all targets with attribute
- let targets = document.querySelectorAll(`[${follow.attribute}]`)
-
- // debug
- follow.log('targets', targets)
-
- for (let target of targets) {
- // set the specified or the default factor
- let factor = target.getAttribute(follow.attribute) ? target.getAttribute(follow.attribute) : follow.defaultFactor
-
- // create element object
- let element = {
- factor: factor,
- target: target,
- x: 0,
- y: 0,
- startPosition: {
- x: 0,
- y: 0
- }
- }
-
- // define start position of element to calculate correctly
- element.startPosition.x = element.target.offsetLeft
- element.startPosition.y = element.target.offsetTop
+ // get all targets with attribute
+ let targets = document.querySelectorAll(`[${follow.attribute}]`)
- // push element to array
- follow.elements.push(element)
- }
+ // debug
+ helper.log('targets', targets)
+
+ for (let target of targets) {
+ // set the specified or the default factor
+ let factor = target.getAttribute(follow.attribute) ? target.getAttribute(follow.attribute) : follow.defaultFactor
+
+ // create element object
+ let element = {
+ factor: factor,
+ target: target,
+ x: 0,
+ y: 0,
+ dimensions: {
+ height: 0,
+ width: 0
+ },
+ initialPosition: {
+ x: 0,
+ y: 0
+ },
+ }
+
+ // define dimensions of the element
+ element.dimensions.height = element.target.offsetHeight
+ element.dimensions.width = element.target.offsetWidth
+
+ // define the center of the element as initial position
+ element.initialPosition.x = element.target.offsetLeft + (element.dimensions.width / 2)
+ element.initialPosition.y = element.target.offsetTop + (element.dimensions.height / 2)
+
+ // if center helper is wanted
+ helper.dot(element.initialPosition.x, element.initialPosition.y, 'red', 10000)
+
+ // push element to array
+ follow.elements.push(element)
+ }
- // debug
- follow.log('elements', follow.elements)
+ // debug
+ helper.log('elements', follow.elements)
}
follow.animate = (event) => {
- // define mouse position
- let mouseX = event.clientX
- let mouseY = event.clientY
+ // define mouse position
+ let mouseX = event.clientX
+ let mouseY = event.clientY
+
+ // firefox fallback because mouse is offset by y 15 and x 9 pixel
+ if (navigator.userAgent.search("Firefox") !== -1) {
+ mouseX += 9
+ mouseY += 15
+ }
- // debug
- follow.log('mouseX', mouseX)
- follow.log('mouseY', mouseY)
+ // add dot for mouse
+ helper.dot && helper.dot(mouseX, mouseY, 'blue')
- for (let element of follow.elements) {
// debug
- follow.log('element', element)
+ helper.log('mouseX', mouseX)
+ helper.log('mouseY', mouseY)
- // get current position of element
- element.x = element.target.offsetLeft
- element.y = element.target.offsetTop
+ for (let element of follow.elements) {
+ // debug
+ helper.log('element', element)
- // calculate future position
- let positionX = (mouseX - element.x) / element.factor
- let positionY = (mouseY - element.y) / element.factor
+ // calculate additional pixels
+ let additionalX = (mouseX - element.initialPosition.x) / element.factor
+ let additionalY = (mouseY - element.initialPosition.y) / element.factor
- // debug
- follow.log('future position x', positionX)
- follow.log('future position y', positionY)
+ // calculate future position
+ let futureX = (element.initialPosition.x + additionalX) - (element.dimensions.width / 2)
+ let futureY = (element.initialPosition.y + additionalY) - (element.dimensions.height / 2)
- // set future position
- element.target.style.left = element.startPosition.x + positionX + 'px'
- element.target.style.top = element.startPosition.y + positionY + 'px'
- }
-}
+ // set future position
+ element.target.style.left = futureX + 'px'
+ element.target.style.top = futureY + 'px'
+
+ // add helper dot if wanted
+ helper.dot && helper.dot(futureX, futureY, 'green')
-follow.log = (string, object = undefined) => {
- if (follow.debug) {
- if (object) {
- console.log(string, object)
- } else {
- console.log(string)
+ // debug
+ helper.log('future position x', futureX)
+ helper.log('future position y', futureY)
}
- }
}
follow.init()
diff --git a/webpack.config.js b/webpack.config.js
index f409924..df45aeb 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -7,4 +7,5 @@ module.exports = {
filename: 'follow.min.js'
},
mode: 'production',
+ watch: true
}
\ No newline at end of file