Решение выполнено на движке Matter
Matter.js - это двумерный движок на JavaScript, который позволяет создавать твердые тела и присваивать им физические свойства, такие как масса, площадь или плотность.
Пример:
HTML:
1 2 3 4 |
<div class="eyes"> <div class="eyeball-physics"></div> <div class="eyeball-sprites"></div> </div> |
CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
.eyes { height: 600px; background: #337AB7; position: relative; background: url(mario.jpg); background-size: contain; } .eyeball-physics { position: absolute; width: 100%; height: 100%; left: 0; top: 0; overflow: hidden; } .eyeball-sprites { pointer-events: none; } .eyeball { background: #FFFFFF; border-radius: 100%; overflow: hidden; position: absolute; } .eyeball > div { background: url(eyeball.png); background-size: contain; height: 100%; position: absolute; width: 100%; z-index: 1; } .eyeball::after { background: radial-gradient(ellipse at center, rgba(0,0,0,0) 0, rgba(0,0,0,0) 30%,rgba(0,0,0,2.5) 100%); border-radius: 100%; box-shadow: inset -10px -10px 15px rgba(0,0,0,0.9); content: ''; display: block; height: 140%; left: -30%; position: absolute; top: -30%; width: 140%; z-index: 2; } .eyeball--1 > div { filter: hue-rotate(45deg); } .eyeball--2 > div { filter: hue-rotate(90deg); } .eyeball--3 > div { filter: hue-rotate(195deg); } .eyeball--4 > div { filter: hue-rotate(255deg); } |
JS:
- Подключаем библиотеку matter.min.js
- Подключаем скрипт ниже, в котором
numCircles
- кол-во глаз
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
let container = document.querySelector('.eyes'); let w = container.offsetWidth; let h = container.offsetHeight; const numCircles = 40; let ground; let wall1; let wall2; const content = document.querySelector('.eyeball-physics'); let elements = []; let eyeballs = []; window.addEventListener('resize', (e) => { w = container.offsetWidth; h = container.offsetHeight; engine.render.canvas.width = w; engine.render.canvas.height = h; Matter.Body.setPosition(wall2, Matter.Vector.create(w + 30, h * .5)); Matter.Body.setPosition(ground, Matter.Vector.create(w * .5, h + 30)); }); var engine = Matter.Engine.create(content, { render: { options: { width: w, height: h, wireframes: false, background: "transparent" } } }); window.engine = engine; var mouseConstraint = Matter.MouseConstraint.create(engine, { constraint: { render: { visible: false }, stiffness:0.1 } }); let spritesArea = document.querySelector('.eyeball-sprites'); class Eyeball { constructor() { var x = Math.random() * w; var y = Math.random() * - h; var base = w / 30; if(base < 5) base = 5; if(base > 10) base = 10; var multiplier = w / 10; if(multiplier < 30) multiplier = 30; if(multiplier > 60) multiplier = 60; this.radius = base + (Math.random() * multiplier); this.body = Matter.Bodies.circle(x, y, this.radius, {render: { fillStyle: 'transparent' }}); this.element = document.createElement('div'); this.element.className = 'eyeball ' + 'eyeball--' + Math.floor(Math.random() * 5); this.element.style.width = this.radius * 2 + 'px'; this.element.style.height = this.radius * 2 + 'px'; this.cornea = document.createElement('div'); this.element.appendChild(this.cornea) spritesArea.appendChild(this.element); } update() { this.pos = {x: this.body.position.x, y: this.body.position.y} this.element.style.transform = `translate(${this.pos.x - this.radius}px, ${this.pos.y - this.radius}px)`; } lookAt(pos) { let diff = { x: pos.x - this.pos.x, y: pos.y - this.pos.y }; let polar = [ Math.sqrt( diff.x * diff.x + diff.y * diff.y ), Math.atan2(diff.y, diff.x) ]; let dist = polar[0] < this.radius * .5 ? polar[0] : this.radius * .5; this.cornea.style.transform = `translate(${Math.cos(polar[1]) * dist}px, ${Math.sin(polar[1]) * dist}px)`; window.cornea = `translate(${Math.cos(polar[1]) * dist}px, ${Math.sin(polar[1]) * dist}px)`; window.polar = polar } } let mousepos = {x: 0, y: 0}; window.addEventListener('pointermove', (e) => { mousepos = {x: e.clientX - container.getBoundingClientRect().left, y: e.clientY - container.getBoundingClientRect().top}; }); for(var i = 0; i < numCircles; i++) { eyeballs.push(new Eyeball); } ground = Matter.Bodies.rectangle(w/2, h+30, 50000., 60, { isStatic: true }); wall1 = Matter.Bodies.rectangle(-30, h/2, 60, h*2, { isStatic: true }); wall2 = Matter.Bodies.rectangle(w+30, h/2, 60, h*2, { isStatic: true }); window.wall2 = wall2; elements.push(ground); elements.push(wall1); elements.push(wall2); Matter.World.add(engine.world, eyeballs.map(eyeball => eyeball.body).concat(elements)); Matter.World.add(engine.world, mouseConstraint); Matter.Engine.run(engine); Matter.Events.on(engine, "afterUpdate", () => { eyeballs.forEach((eye) => { eye.update(); eye.lookAt(mousepos); }); }); |
Найдено на codepen.io у пользователя Liam Egan
Библиотека Matter.js
Фотография Alexas_Fotos
Смотрите также:
Бесполезный, но интересный скрипт, генерирующий случаным образом сов
Юмористическая сцена с выключающим лампочку медведем
Шуточный пример входной страницы сайта
Добавить комментарий: