├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── package.json └── src ├── css └── base.css ├── favicon.ico ├── img └── waveline.svg ├── index.html ├── index2.html ├── index3.html ├── index4.html ├── index5.html ├── index6.html └── js ├── animatedLink.js └── index.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.cache 3 | /dist 4 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Manoela Ilic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Distortion Effect Ideas for Menu Links 2 | 3 | Some menu styles and ideas for decorative link distortion effects using SVG filters. 4 | 5 | ![DistortedMenuLinkEffects](https://tympanus.net/codrops/wp-content/uploads/2020/03/LinkEffects_featured.png) 6 | 7 | [Article on Codrops](https://tympanus.net/codrops/?p=48586) 8 | 9 | [Demo](http://tympanus.net/Development/DistortedMenuLinkEffects/) 10 | 11 | 12 | ## Installation 13 | 14 | Install dependencies: 15 | 16 | ``` 17 | npm install 18 | ``` 19 | 20 | Compile the code for development and start a local server: 21 | 22 | ``` 23 | npm start 24 | ``` 25 | 26 | Create the build: 27 | 28 | ``` 29 | npm run build 30 | ``` 31 | 32 | ## Misc 33 | 34 | Follow Codrops: [Twitter](http://www.twitter.com/codrops), [Facebook](http://www.facebook.com/codrops), [GitHub](https://github.com/codrops), [Instagram](https://www.instagram.com/codropsss/) 35 | 36 | ## License 37 | [MIT](LICENSE) 38 | 39 | Made with :blue_heart: by [Codrops](http://www.codrops.com) 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LinkDistortionEffectIdeas", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "parcel src/index.html --open", 8 | "clean": "rm -rf dist/*", 9 | "build:parcel": "parcel build src/index.html --no-minify --no-source-maps --public-url ./", 10 | "build": "npm run clean && npm run build:parcel" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/codrops/LinkDistortionEffectIdeas.git" 15 | }, 16 | "keywords": [], 17 | "author": "Codrops", 18 | "license": "MIT", 19 | "homepage": "https://tympanus.net/Development/LinkDistortionEffectIdeas/", 20 | "bugs": { 21 | "url": "https://github.com/codrops/LinkDistortionEffectIdeas/issues" 22 | }, 23 | "dependencies": { 24 | "gsap": "^3.2.2", 25 | "parcel-bundler": "^1.12.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/css/base.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | } 6 | 7 | :root { 8 | font-size: 13px; 9 | } 10 | 11 | body { 12 | margin: 0; 13 | --color-text: #fff; 14 | --color-bg: #191818; 15 | --color-link: #484848; 16 | --color-link-hover: #fff; 17 | --color-menu: #fff; 18 | --color-menu-hover: #2a2727; 19 | --color-deco: linear-gradient(90deg, rgb(225, 16, 250) 0%, rgba(128,29,253,1) 50%); 20 | --font-menu: brother-1816, sans-serif; 21 | --font-size-menu: 10vw; 22 | --font-weight-menu: 900; 23 | --ttransfrom-menu: uppercase; 24 | --thickness-deco: 40px; 25 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif; 26 | color: var(--color-text); 27 | background-color: var(--color-bg); 28 | -webkit-font-smoothing: antialiased; 29 | -moz-osx-font-smoothing: grayscale; 30 | } 31 | 32 | .demo-2 { 33 | --color-text: #000; 34 | --color-bg: #ffdfec; 35 | --color-link: #ff0063; 36 | --color-link-hover: #000; 37 | --color-menu: #000; 38 | --color-menu-hover: #ff0563; 39 | --color-deco: #000; 40 | --font-menu: titling-gothic-fb-wide, sans-serif; 41 | --ttransfrom-menu: uppercase; 42 | --font-size-menu: 8vw; 43 | --font-weight-menu: 800; 44 | --thickness-deco: 2px; 45 | --stroke-color-menu: #000; 46 | --stroke-fill-menu: #fff; 47 | --stroke-width-menu: 2px; 48 | } 49 | 50 | .demo-3 { 51 | --color-text: #ffffff; 52 | --color-bg: #cecece; 53 | --color-link: #e81a1a; 54 | --color-link-hover: #000; 55 | --color-menu: #000000; 56 | --color-menu-hover: #ffffff; 57 | --color-deco: #e81a1a; 58 | --font-menu: bely-display, sans-serif; 59 | --ttransfrom-menu: uppercase; 60 | --font-size-menu: 5vw; 61 | --font-weight-menu: 400; 62 | --thickness-deco: 2px; 63 | } 64 | 65 | .demo-4 { 66 | --color-text: #000; 67 | --color-bg: #e2e1c9; 68 | --color-link: #f9043d; 69 | --color-link-hover: #000; 70 | --color-menu: #000; 71 | --color-menu-hover: #000; 72 | --color-deco: #000; 73 | --font-menu: freight-big-pro, serif; 74 | --ttransfrom-menu: none; 75 | --font-size-menu: 8vw; 76 | --font-weight-menu: 300; 77 | --thickness-deco: 2px; 78 | } 79 | 80 | .demo-5 { 81 | --color-text: #5f5f5f; 82 | --color-bg: #0c0c0c; 83 | --color-link: #f3f3f3; 84 | --color-link-hover: #da154b; 85 | --color-menu: #fff; 86 | --color-menu-hover: #da154b; 87 | --color-deco: #da154b; 88 | --font-menu: rigatoni, serif; 89 | --ttransfrom-menu: uppercase; 90 | --font-size-menu: 9vw; 91 | --font-weight-menu: 400; 92 | --thickness-deco: 1px; 93 | } 94 | 95 | .demo-6 { 96 | --color-text: #000; 97 | --color-bg: #d0d0d0; 98 | --color-link: #1b36ce; 99 | --color-link-hover: #000; 100 | --color-menu: #F91C1C; 101 | --color-menu-hover: #1b36ce; 102 | --color-deco: #F91C1C; 103 | --font-menu: titling-gothic-fb-extended, sans-serif;; 104 | --ttransfrom-menu: uppercase; 105 | --font-size-menu: 5.5vw; 106 | --font-weight-menu: 500; 107 | } 108 | 109 | .hidden { 110 | position: absolute; 111 | overflow: hidden; 112 | width: 0; 113 | height: 0; 114 | pointer-events: none; 115 | } 116 | 117 | a { 118 | text-decoration: none; 119 | color: var(--color-link); 120 | outline: none; 121 | } 122 | 123 | a:hover, 124 | a:focus { 125 | color: var(--color-link-hover); 126 | outline: none; 127 | } 128 | 129 | main { 130 | padding: 3rem 5rem 20vh; 131 | } 132 | 133 | .frame { 134 | text-align: center; 135 | margin-bottom: 20vh; 136 | font-weight: bold; 137 | } 138 | 139 | .frame > *:not(:last-child) { 140 | margin-bottom: 1rem; 141 | } 142 | 143 | .frame__title { 144 | font-size: 1rem; 145 | margin: 0 0 0.25rem; 146 | } 147 | 148 | .frame__links > *:not(:last-child), 149 | .frame__demos > *:not(:last-child) { 150 | margin-right: 1rem; 151 | } 152 | 153 | .frame__demo--current, 154 | .frame__demo--current:hover { 155 | color: var(--color-text); 156 | } 157 | 158 | .menu { 159 | display: flex; 160 | flex-direction: column; 161 | flex-wrap: wrap; 162 | align-items: start; 163 | } 164 | 165 | .menu__link { 166 | padding-bottom: 0.5rem; 167 | margin-bottom: 2.5rem; 168 | font-size: var(--font-size-menu); 169 | font-weight: var(--font-weight-menu); 170 | font-family: var(--font-menu); 171 | position: relative; 172 | line-height: 1; 173 | color: var(--color-menu); 174 | text-transform: var(--ttransfrom-menu); 175 | -webkit-touch-callout: none; 176 | -webkit-user-select: none; 177 | -moz-user-select: none; 178 | -ms-user-select: none; 179 | user-select: none; 180 | } 181 | 182 | .menu__link:hover { 183 | color: var(--color-menu-hover); 184 | -webkit-text-fill-color: var(--color-menu-hover); 185 | text-fill-color: var(--color-menu-hover); 186 | } 187 | 188 | .demo-1 .menu__link, 189 | .demo-6 .menu__link { 190 | letter-spacing: -0.85vw; 191 | padding-right: 0.85vw; 192 | } 193 | 194 | .menu__link--outline { 195 | -webkit-text-stroke: var(--stroke-width-menu) var(--stroke-color-menu); 196 | text-stroke: var(--stroke-width-menu) var(--stroke-color-menu); 197 | -webkit-text-fill-color: var(--stroke-fill-menu); 198 | text-fill-color: var(--stroke-fill-menu); 199 | color: transparent; 200 | } 201 | 202 | .menu__link-inner { 203 | display: block; 204 | position: relative; 205 | outline: 100px solid transparent; 206 | } 207 | 208 | .menu__link-deco { 209 | outline: 120px solid transparent; 210 | opacity: 0; 211 | position: absolute; 212 | pointer-events: none; 213 | } 214 | 215 | .menu--wave .menu__link-deco, 216 | .menu--line .menu__link-deco, 217 | .menu--linethrough .menu__link-deco, 218 | .menu--twolines .menu__link-deco, 219 | .menu--linebefore .menu__link-deco { 220 | bottom: 0; 221 | left: 0; 222 | height: var(--thickness-deco); 223 | width: 100%; 224 | background: var(--color-deco); 225 | } 226 | 227 | .menu--wave .menu__link { 228 | margin-bottom: 4rem; 229 | } 230 | 231 | .menu--wave .menu__link-deco { 232 | height: calc(100% + 2vw); 233 | width: calc(100% + 2vw); 234 | left: -1vw; 235 | top: -1vw; 236 | background: url(../img/waveline.svg) repeat-x 0% 50%; 237 | background-size: 20vw 40vw; 238 | z-index: -1; 239 | border: 12px solid var(--color-deco); 240 | } 241 | 242 | .menu--linethrough .menu__link-deco { 243 | bottom: calc(50% - (var(--thickness-deco) / 2)); 244 | } 245 | 246 | .menu--twolines .menu__link-deco { 247 | height: 100%; 248 | background: none; 249 | border: var(--thickness-deco) solid var(--color-deco); 250 | border-right: 0; 251 | border-left: 0; 252 | } 253 | 254 | .menu--twolines .menu__link { 255 | padding: 0.95rem 0; 256 | } 257 | 258 | .menu--circle .menu__link-deco { 259 | left: 0; 260 | top: 43%; 261 | width: 8vw; 262 | height: 8vw; 263 | margin: -4vw 0 0 0; 264 | background: var(--color-deco); 265 | z-index: -1; 266 | } 267 | 268 | .menu--circle .menu__link-deco { 269 | border-radius: 50%; 270 | } 271 | 272 | .menu--circle .menu__link:hover .menu__link-inner { 273 | transform: translate3d(10vw,0,0); 274 | } 275 | 276 | .menu--linebefore .menu__link-deco { 277 | width: 6vw; 278 | bottom: calc(50% - (var(--thickness-deco) / 2)); 279 | } 280 | 281 | .menu--linebefore .menu__link:hover .menu__link-inner { 282 | font-style: italic; 283 | transform: translateX(6.5vw); 284 | } 285 | 286 | .menu__link:hover .menu__link-deco { 287 | opacity: 1; 288 | } 289 | 290 | @media screen and (min-width: 53em) { 291 | .frame { 292 | width: 100%; 293 | text-align: left; 294 | display: flex; 295 | align-items: start; 296 | } 297 | .frame__demos { 298 | margin-left: auto; 299 | } 300 | .frame > *:not(:last-child) { 301 | margin: 0 2rem 0 0; 302 | display: inline-block; 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/DistortedMenuLinkEffects/5f2f934d8f56845932f6b042af99a9ef81c199d4/src/favicon.ico -------------------------------------------------------------------------------- /src/img/waveline.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Distortion Effect Ideas for Menu Links | Demo 1 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 52 |
53 |
54 |

Distortion Effect Ideas for Menu Links

55 | 59 |
60 | demo 1 61 | demo 2 62 | demo 3 63 | demo 4 64 | demo 5 65 | demo 6 66 |
67 |
68 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Distortion Effect Ideas for Menu Links | Demo 2 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 52 |
53 |
54 |

Distortion Effect Ideas for Menu Links

55 | 59 |
60 | demo 1 61 | demo 2 62 | demo 3 63 | demo 4 64 | demo 5 65 | demo 6 66 |
67 |
68 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Distortion Effect Ideas for Menu Links | Demo 3 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 52 |
53 |
54 |

Distortion Effect Ideas for Menu Links

55 | 59 |
60 | demo 1 61 | demo 2 62 | demo 3 63 | demo 4 64 | demo 5 65 | demo 6 66 |
67 |
68 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/index4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Distortion Effect Ideas for Menu Links | Demo 4 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 52 |
53 |
54 |

Distortion Effect Ideas for Menu Links

55 | 59 |
60 | demo 1 61 | demo 2 62 | demo 3 63 | demo 4 64 | demo 5 65 | demo 6 66 |
67 |
68 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/index5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Distortion Effect Ideas for Menu Links | Demo 5 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 52 |
53 |
54 |

Distortion Effect Ideas for Menu Links

55 | 59 |
60 | demo 1 61 | demo 2 62 | demo 3 63 | demo 4 64 | demo 5 65 | demo 6 66 |
67 |
68 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/index6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Distortion Effect Ideas for Menu Links | Demo 6 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 52 |
53 |
54 |

Distortion Effect Ideas for Menu Links

55 | 59 |
60 | demo 1 61 | demo 2 62 | demo 3 63 | demo 4 64 | demo 5 65 | demo 6 66 |
67 |
68 | 77 |
78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/js/animatedLink.js: -------------------------------------------------------------------------------- 1 | import { gsap } from 'gsap'; 2 | 3 | class LinkFx { 4 | constructor(el) { 5 | this.DOM = {el: el}; 6 | this.options = { 7 | animation: { 8 | text: false, 9 | line: true 10 | } 11 | }; 12 | this.DOM.text = document.createElement('span'); 13 | this.DOM.text.classList = 'menu__link-inner'; 14 | this.DOM.text.innerHTML = this.DOM.el.innerHTML; 15 | this.DOM.el.innerHTML = ''; 16 | this.DOM.el.appendChild(this.DOM.text); 17 | this.DOM.line = document.createElement('span'); 18 | this.DOM.line.classList = 'menu__link-deco'; 19 | this.DOM.el.appendChild(this.DOM.line); 20 | 21 | this.DOM.el.dataset.text != undefined && (this.options.animation.text = this.DOM.el.dataset.text === 'false' ? false : true); 22 | this.DOM.el.dataset.line != undefined && (this.options.animation.line = this.DOM.el.dataset.line === 'false' ? false : true); 23 | 24 | this.initEvents(); 25 | } 26 | initEvents() { 27 | this.onMouseEnterFn = () => this.tl.restart(); 28 | this.onMouseLeaveFn = () => this.tl.progress(1).kill(); 29 | this.DOM.el.addEventListener('mouseenter', this.onMouseEnterFn); 30 | this.DOM.el.addEventListener('mouseleave', this.onMouseLeaveFn); 31 | } 32 | createTimeline() { 33 | // init timeline 34 | this.tl = gsap.timeline({ 35 | paused: true, 36 | onStart: () => { 37 | if ( this.options.animation.line ) { 38 | this.DOM.line.style.filter = `url(${this.filterId}`; 39 | } 40 | if ( this.options.animation.text ) { 41 | this.DOM.text.style.filter = `url(${this.filterId}`; 42 | } 43 | }, 44 | onComplete: () => { 45 | if ( this.options.animation.line ) { 46 | this.DOM.line.style.filter = 'none'; 47 | } 48 | if ( this.options.animation.text ) { 49 | this.DOM.text.style.filter = 'none' 50 | } 51 | } 52 | }); 53 | } 54 | } 55 | 56 | class LinkFx1 extends LinkFx { 57 | constructor(el) { 58 | super(el); 59 | this.filterId = '#filter-1'; 60 | this.DOM.feTurbulence = document.querySelector(`${this.filterId} > feTurbulence`); 61 | this.primitiveValues = {turbulence: 0}; 62 | 63 | this.createTimeline(); 64 | this.tl.eventCallback('onUpdate', () => this.DOM.feTurbulence.setAttribute('baseFrequency', this.primitiveValues.turbulence)); 65 | this.tl.to(this.primitiveValues, { 66 | duration: 0.4, 67 | //ease: "Quint.easeOut", 68 | startAt: {turbulence: 0.09}, 69 | turbulence: 0 70 | }); 71 | } 72 | } 73 | 74 | class LinkFx2 extends LinkFx { 75 | constructor(el) { 76 | super(el); 77 | this.filterId = '#filter-2'; 78 | this.DOM.feTurbulence = document.querySelector(`${this.filterId} > feTurbulence`); 79 | this.primitiveValues = {turbulence: 0}; 80 | 81 | this.createTimeline(); 82 | this.tl.eventCallback('onUpdate', () => this.DOM.feTurbulence.setAttribute('baseFrequency', this.primitiveValues.turbulence)); 83 | this.tl.to(this.primitiveValues, { 84 | duration: 0.4, 85 | ease: "rough({ template: none.out, strength: 2, points: 120, taper: 'none', randomize: true, clamp: false})", 86 | startAt: {turbulence: 0.07}, 87 | turbulence: 0 88 | }); 89 | } 90 | } 91 | 92 | class LinkFx3 extends LinkFx { 93 | constructor(el) { 94 | super(el); 95 | this.filterId = '#filter-3'; 96 | this.DOM.feDisplacementMap = document.querySelector(`${this.filterId} > feDisplacementMap`); 97 | this.primitiveValues = {scale: 0}; 98 | 99 | this.createTimeline(); 100 | this.tl.eventCallback('onUpdate', () => this.DOM.feDisplacementMap.scale.baseVal = this.primitiveValues.scale); 101 | this.tl.to(this.primitiveValues, { 102 | duration: 0.1, 103 | ease: 'Expo.easeOut', 104 | startAt: {scale: 0}, 105 | scale: 60 106 | }) 107 | .to(this.primitiveValues, { 108 | duration: 0.6, 109 | ease: 'Back.easeOut', 110 | //startAt: {scale: 90}, 111 | scale: 0 112 | }); 113 | } 114 | } 115 | 116 | class LinkFx4 extends LinkFx { 117 | constructor(el) { 118 | super(el); 119 | this.filterId = '#filter-4'; 120 | this.DOM.feTurbulence = document.querySelector(`${this.filterId} > feTurbulence`); 121 | this.primitiveValues = {turbulence: 0}; 122 | 123 | this.createTimeline(); 124 | this.tl.eventCallback('onUpdate', () => this.DOM.feTurbulence.setAttribute('baseFrequency', this.primitiveValues.turbulence)); 125 | this.tl.to(this.primitiveValues, { 126 | duration: 0.6, 127 | ease: "steps(12)", 128 | startAt: {turbulence: 0.05}, 129 | turbulence: 0 130 | }); 131 | } 132 | } 133 | 134 | class LinkFx5 extends LinkFx { 135 | constructor(el) { 136 | super(el); 137 | this.filterId = '#filter-5'; 138 | this.DOM.feDisplacementMap = document.querySelector(`${this.filterId} > feDisplacementMap`); 139 | this.primitiveValues = {scale: 0}; 140 | 141 | this.createTimeline(); 142 | this.tl.eventCallback('onUpdate', () => this.DOM.feDisplacementMap.scale.baseVal = this.primitiveValues.scale); 143 | this.tl 144 | /*.to(this.primitiveValues, { 145 | duration: 0.1, 146 | ease: 'Power1.easeOut', 147 | startAt: {scale: 0}, 148 | scale: 40 149 | }) 150 | .to(this.primitiveValues, { 151 | duration: 0.7, 152 | ease: 'Expo.easeOut', 153 | scale: 0 154 | })*/ 155 | .to(this.primitiveValues, { 156 | duration: 0.7, 157 | startAt: {scale: 40}, 158 | //ease: 'Expo.easeOut', 159 | ease: "rough({ template: none.out, strength: 2, points: 120, taper: 'none', randomize: true, clamp: false})", 160 | scale: 0 161 | }, 0) 162 | .to(this.DOM.line, { 163 | duration: 0.7, 164 | startAt: {y: -5}, 165 | ease: 'Expo.easeOut', 166 | y: 0 167 | }, 0); 168 | } 169 | } 170 | 171 | class LinkFx6 extends LinkFx { 172 | constructor(el) { 173 | super(el); 174 | this.filterId = '#filter-6'; 175 | this.DOM.feDisplacementMap = document.querySelector(`${this.filterId} > feDisplacementMap`); 176 | this.primitiveValues = {scale: 0}; 177 | 178 | this.createTimeline(); 179 | this.tl.eventCallback('onUpdate', () => this.DOM.feDisplacementMap.scale.baseVal = this.primitiveValues.scale); 180 | this.tl.to(this.primitiveValues, { 181 | duration: 1, 182 | ease: 'Expo.easeOut', 183 | startAt: {scale: 80}, 184 | scale: 0 185 | }); 186 | } 187 | } 188 | 189 | class LinkFx7 extends LinkFx { 190 | constructor(el) { 191 | super(el); 192 | this.filterId = '#filter-7'; 193 | this.DOM.feTurbulence = document.querySelector(`${this.filterId} > feTurbulence`); 194 | this.primitiveValues = {turbulence: 0}; 195 | 196 | this.createTimeline(); 197 | this.tl.eventCallback('onUpdate', () => this.DOM.feTurbulence.setAttribute('baseFrequency', this.primitiveValues.turbulence)); 198 | this.tl.to(this.primitiveValues, { 199 | duration: 0.4, 200 | ease: 'Expo.easeOut', 201 | startAt: {turbulence: 0}, 202 | turbulence: 1 203 | }); 204 | } 205 | } 206 | 207 | export default [LinkFx1, LinkFx2, LinkFx3, LinkFx4, LinkFx5, LinkFx6, LinkFx7]; -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | import AnimatedLinksObjs from "./animatedLink"; 2 | 3 | [...document.querySelectorAll('a.menu__link')].forEach((el) => { 4 | const elPosition = [...el.parentNode.children].indexOf(el); 5 | const fxObj = AnimatedLinksObjs[elPosition]; 6 | fxObj && new fxObj(el); 7 | }); 8 | --------------------------------------------------------------------------------