kuban-forum.ru - Лучший форум для общения

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » kuban-forum.ru - Лучший форум для общения » 🍰Кофейня » ;;;;CSS / JS трюки :)


;;;;CSS / JS трюки :)

Сообщений 1 страница 8 из 8

1

Тема для всякого-разного, вставляемого через  html теги.

Подпись автора

Функционал форума Книга жалоб Книга предложений Знак зодиака Как вставить видео на форум Форум"Грибные места" Слайдер для картинок Live-box с темами

0

2

Часы

[html]<div id="watch"><div class="frame-face"></div><ul class="minute-marks"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><ul class="digits"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li></ul><div class="hours-hand"></div><div class="minutes-hand"></div><div class="seconds-hand"></div></div><style>body{font-size:62.5%;margin:1em;background:#232425}ul{list-style:none;margin:0;padding:0}#watch{font-size:1em;position:relative}#watch .frame-face{position:relative;width:30em;height:30em;margin:2em auto;border-radius:15em;background:-webkit-linear-gradient(top,#f9f9f9,#666);background:-moz-linear-gradient(top,#f9f9f9,#666);background:linear-gradient(to bottom,#f9f9f9,#666);box-shadow:rgba(0,0,0,.8) .5em .5em 4em}#watch .frame-face:before{content:'';width:29.4em;height:29.4em;border-radius:14.7em;position:absolute;top:.3em;left:.3em;background:-webkit-linear-gradient(135deg,rgba(246,248,249,0) 0%,rgba(229,235,238,1) 50%,rgba(205,212,217,1) 51%,rgba(245,247,249,0) 100%),-webkit-radial-gradient(center,ellipse cover,rgba(246,248,249,1) 0%,rgba(229,235,238,1) 65%,rgba(205,212,217,1) 66%,rgba(245,247,249,1) 100%);background:-moz-linear-gradient(135deg,rgba(246,248,249,0) 0%,rgba(229,235,238,1) 50%,rgba(205,212,217,1) 51%,rgba(245,247,249,0) 100%),-moz-radial-gradient(center,ellipse cover,rgba(246,248,249,1) 0%,rgba(229,235,238,1) 65%,rgba(205,212,217,1) 66%,rgba(245,247,249,1) 100%);background:linear-gradient(135deg,rgba(246,248,249,0) 0%,rgba(229,235,238,1) 50%,rgba(205,212,217,1) 51%,rgba(245,247,249,0) 100%),radial-gradient(ellipse at center,rgba(246,248,249,1) 0%,rgba(229,235,238,1) 65%,rgba(205,212,217,1) 66%,rgba(245,247,249,1) 100%)}#watch .frame-face:after{content:'';width:28em;height:28em;border-radius:14.2em;position:absolute;top:.9em;left:.9em;box-shadow:inset rgba(0,0,0,.2) .2em .2em 1em;border:.1em solid rgba(0,0,0,.2);background:-webkit-linear-gradient(top,#fff,#ccc);background:-moz-linear-gradient(top,#fff,#ccc);background:linear-gradient(to bottom,#fff,#ccc)}#watch .minute-marks li{display:block;width:.2em;height:.6em;background:#929394;position:absolute;top:50%;left:50%;margin:-.4em 0 0 -.1em}#watch .minute-marks li:first-child{transform:rotate(6deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(2){transform:rotate(12deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(3){transform:rotate(18deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(4){transform:rotate(24deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(5){transform:rotate(36deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(6){transform:rotate(42deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(7){transform:rotate(48deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(8){transform:rotate(54deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(9){transform:rotate(66deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(10){transform:rotate(72deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(11){transform:rotate(78deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(12){transform:rotate(84deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(13){transform:rotate(96deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(14){transform:rotate(102deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(15){transform:rotate(108deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(16){transform:rotate(114deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(17){transform:rotate(126deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(18){transform:rotate(132deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(19){transform:rotate(138deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(20){transform:rotate(144deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(21){transform:rotate(156deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(22){transform:rotate(162deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(23){transform:rotate(168deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(24){transform:rotate(174deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(25){transform:rotate(186deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(26){transform:rotate(192deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(27){transform:rotate(198deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(28){transform:rotate(204deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(29){transform:rotate(216deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(30){transform:rotate(222deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(31){transform:rotate(228deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(32){transform:rotate(234deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(33){transform:rotate(246deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(34){transform:rotate(252deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(35){transform:rotate(258deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(36){transform:rotate(264deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(37){transform:rotate(276deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(38){transform:rotate(282deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(39){transform:rotate(288deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(40){transform:rotate(294deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(41){transform:rotate(306deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(42){transform:rotate(312deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(43){transform:rotate(318deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(44){transform:rotate(324deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(45){transform:rotate(336deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(46){transform:rotate(342deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(47){transform:rotate(348deg) translateY(-12.7em)}#watch .minute-marks li:nth-child(48){transform:rotate(354deg) translateY(-12.7em)}#watch .digits{width:30em;height:30em;border-radius:15em;position:absolute;top:0;left:50%;margin-left:-15em}#watch .digits li{font-size:1.6em;display:block;width:1.6em;height:1.6em;position:absolute;top:50%;left:50%;line-height:1.6em;text-align:center;margin:-.8em 0 0 -.8em;font-weight:bold}#watch .digits li:nth-child(1){transform:translate(3.9em,-6.9em)}#watch .digits li:nth-child(2){transform:translate(6.9em,-4em)}#watch .digits li:nth-child(3){transform:translate(8em,0)}#watch .digits li:nth-child(4){transform:translate(6.8em,4em)}#watch .digits li:nth-child(5){transform:translate(3.9em,6.9em)}#watch .digits li:nth-child(6){transform:translate(0,8em)}#watch .digits li:nth-child(7){transform:translate(-3.9em,6.9em)}#watch .digits li:nth-child(8){transform:translate(-6.8em,4em)}#watch .digits li:nth-child(9){transform:translate(-8em,0)}#watch .digits li:nth-child(10){transform:translate(-6.9em,-4em)}#watch .digits li:nth-child(11){transform:translate(-3.9em,-6.9em)}#watch .digits li:nth-child(12){transform:translate(0,-8em)}#watch .digits:before{content:'';width:1.6em;height:1.6em;border-radius:.8em;position:absolute;top:50%;left:50%;margin:-.8em 0 0 -.8em;background:#121314}#watch .digits:after{content:'';width:4em;height:4em;border-radius:2.2em;position:absolute;top:50%;left:50%;margin:-2.1em 0 0 -2.1em;border:.1em solid #c6c6c6;background:-webkit-radial-gradient(center,ellipse cover,rgba(200,200,200,0),rgba(190,190,190,1) 90%,rgba(130,130,130,1) 100%);background:-moz-radial-gradient(center,ellipse cover,rgba(200,200,200,0),rgba(190,190,190,1) 90%,rgba(130,130,130,1) 100%);background:radial-gradient(ellipse at center,rgba(200,200,200,0),rgba(190,190,190,1) 90%,rgba(130,130,130,1) 100%)}#watch .hours-hand{width:.8em;height:7em;border-radius:0 0 .9em .9em;background:#232425;position:absolute;bottom:50%;left:50%;margin:0 0 -.8em -.4em;box-shadow:#232425 0 0 2px;transform-origin:.4em 6.2em}#watch .hours-hand:before{content:'';background:inherit;width:1.8em;height:.8em;border-radius:0 0 .8em .8em;box-shadow:#232425 0 0 1px;position:absolute;top:-.7em;left:-.5em}#watch .hours-hand:after{content:'';width:0;height:0;border:.9em solid #232425;border-width:0 .9em 2.4em .9em;border-left-color:transparent;border-right-color:transparent;position:absolute;top:-3.1em;left:-.5em}#watch .minutes-hand{width:.8em;height:12.5em;border-radius:.5em;background:#343536;position:absolute;bottom:50%;left:50%;margin:0 0 -1.5em -.4em;box-shadow:#343536 0 0 2px;transform-origin:.4em 11em}#watch .seconds-hand{width:.2em;height:14em;border-radius:.1em .1em 0 0/10em 10em 0 0;background:#c00;position:absolute;bottom:50%;left:50%;margin:0 0 -2em -.1em;box-shadow:rgba(0,0,0,.8) 0 0 .2em;transform-origin:.1em 12em}#watch .seconds-hand:after{content:'';width:1.4em;height:1.4em;border-radius:.7em;background:inherit;position:absolute;left:-.65em;bottom:1.35em}#watch .seconds-hand:before{content:'';width:.8em;height:3em;border-radius:.2em .2em .4em .4em/.2em .2em 2em 2em;box-shadow:rgba(0,0,0,.8) 0 0 .2em;background:inherit;position:absolute;left:-.35em;bottom:-3em}</style><script>function updateWatch(){const now=new Date(),hours=now.getHours()%12,minutes=now.getMinutes(),seconds=now.getSeconds(),hoursRotation=(hours+minutes/60)*30,minutesRotation=(minutes+seconds/60)*6,secondsRotation=seconds*6;document.querySelector('.hours-hand').style.transform=`rotate(${hoursRotation}deg)`,document.querySelector('.minutes-hand').style.transform=`rotate(${minutesRotation}deg)`,document.querySelector('.seconds-hand').style.transform=`rotate(${secondsRotation}deg)`}setInterval(updateWatch,1000),updateWatch();</script>[/html]

Подпись автора

Функционал форума Книга жалоб Книга предложений Знак зодиака Как вставить видео на форум Форум"Грибные места" Слайдер для картинок Live-box с темами

0

3

30006,2 написал(а):

Тема для всякого-разного, вставляемого через  html теги.

темка хорошА, я тоже люблю всякие "оживляшки", иногда практикуюсь на девочке, которая вынуждена сопровождать мою работу на стороне клиента :) Так сказать, back-end.

И чтоб ей скучно не было, я запускал разные приколы... твой паучок в углу - как раз из этой серии. Иногда просто дразнил ее, находящуюся на работе в вечной спешке (она вообще-то логист, а тут еще и сайт ей навалили) - делал админку в стиле пляжного отдыха под пальмами (SVG, CSS-анимация, немного JS). А уж часики... или разноцветные птицы (SVG mask), летающие через экран... короче, не думаю, что она отдыхала, заходя в админку. Но от работы отвлекалась точно :)

Сейчас настали черные дни в работе моего заказчика. И буквально 6 часов назад я загрузил механизм, позволяющий убить стартовую страницу сайта. На которой цены. И они это сделали - теперь там нет цен, звоните и узнавайте, все ручками. Такая вот извращенная конкуренция нынче - в эпоху стоящего насмерть экспорта, параллельного импорта и теневого флота (могу пояснить детали, ибо это - не фигура речи). Ну и отсутствия экономической активности... как сказал мне сегодня их директор в телефонной беседе "никто не покупает, нет производства и крупных строек, все только продовольствие покупают... я тоже".

И на этом фоне... я перестал думать о веселье на back-end'e. Ну а на фронт-энде (твои часики) - почему бы нет?

Подпись автора

"Я не собираюсь расшифровывать, шиза это или такое чувство юмора. По умолчанию - шиза."(С)

+1

4

upd: девизом в моей админке (первой строчкой с хорошим шрифтом и стилем) служит строка из Библии (сам-то я неверующий, если помнишь):

"и ищущий находит, и стучащемуся отворят" (Лк 11:10)

Что означает - не бойтесь спрашивать, узнавать новое, пробовать применить... В моем понимании, ессно.

Подпись автора

"Я не собираюсь расшифровывать, шиза это или такое чувство юмора. По умолчанию - шиза."(С)

0

5

30014,57 написал(а):


Туман на фотографии, который убирается:
⊹ курсором 🐭мыши на 💻компе
👇🏻пальцем на 📲сенсорных устройствах

Это всего лишь один класс CSS (filter). Кстати, меня всегда забавляла реализация псевдокласса :hover на  touchscreen. Она всегда с чем-нить конфликтует. Так что, не советую ее использовать.

Отредактировано Severin (29.10.2025 22:20:25)

Подпись автора

"Я не собираюсь расшифровывать, шиза это или такое чувство юмора. По умолчанию - шиза."(С)

+1

6


Туман на фотографии, который убирается:
⊹ курсором 🐭мыши на 💻компе
👇🏻пальцем на 📲сенсорных устройствах

[html]<div class="fog-container"><canvas id="fog"></canvas><canvas id="fog-bg"></canvas><canvas id="brush"></canvas><svg id="brush-cursor" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><circle cx="24" cy="24" r="20" fill="none" stroke="white" stroke-width="2" stroke-opacity="0.7"/><circle cx="24" cy="24" r="12" fill="white" fill-opacity="0.15"/></svg></div><button id="reset-fog" type="button">Вернуть туман</button><style>
.fog-container{aspect-ratio:16/9;position:relative;overflow:hidden;margin:20px 0;border-radius:6px;touch-action:none;width:100%;cursor:none}
@media (min-width:768px){.fog-container{max-width:60rem;margin-left:auto;margin-right:auto}}
.fog-container canvas{display:block;width:100%;height:100%;position:absolute;left:50%;top:0;transform:translateX(-50%)}
#brush{opacity:0}
#brush-cursor{position:fixed;pointer-events:none;width:40px;height:40px;margin:0;top:0;left:0;z-index:1000;opacity:0;transition:opacity 0.15s ease;transform:translate(-50%,-50%);filter:drop-shadow(0 0 3px rgba(0,0,0,0.4))}
#reset-fog{display:block;margin:20px auto;padding:12px 24px;background:rgba(0,0,0,0.3);color:white;border:1px solid rgba(255,255,255,0.7);border-radius:6px;cursor:pointer;font-size:16px;font-weight:500;backdrop-filter:blur(4px);outline:none}
@media (hover:hover) and (pointer:fine){
  #reset-fog::before{content:'';position:absolute;bottom:0;left:0;width:100%;height:100%;background:rgba(255,255,255,0.15);backdrop-filter:blur(4px);transform:translateY(100%);transition:transform 0.4s cubic-bezier(0.22,0.61,0.36,1);z-index:0}
  #reset-fog span{position:relative;z-index:1}
  #reset-fog:hover{border-color:rgba(255,255,255,0.8)}
  #reset-fog:hover::before{transform:translateY(0)}
}
#reset-fog:active{border-color:rgba(255,255,255,0.9);background:rgba(0,0,0,0.4);transform:scale(0.98);transition:transform 0.1s ease}
#reset-fog:focus-visible{outline:2px solid #fff;outline-offset:2px}
@media (max-width:480px){#reset-fog{padding:9px 20px;font-size:15px}}
@media (pointer:coarse){.fog-container{cursor:auto!important}#brush-cursor{display:none!important}}
</style><script>
class FogParticle {
  constructor(ctx, canvasWidth, canvasHeight) {
    this.ctx = ctx;
    this.canvasWidth = canvasWidth;
    this.canvasHeight = canvasHeight;
    this.x = 0;
    this.y = 0;
  }
  setPosition(x, y) { this.x = x; this.y = y; }
  setVelocity(x, y) { this.xVelocity = x; this.yVelocity = y; }
  setImage(image) { this.image = image; }
  render() {
    if (!this.image) return;
    this.ctx.drawImage(this.image, this.x - this.image.width / 2, this.y - this.image.height / 2, 400, 400);
    this.x += this.xVelocity; this.y += this.yVelocity;
    if (this.x >= this.canvasWidth) { this.xVelocity = -this.xVelocity; this.x = this.canvasWidth; }
    else if (this.x <= 0) { this.xVelocity = -this.xVelocity; this.x = 0; }
    if (this.y >= this.canvasHeight) { this.yVelocity = -this.yVelocity; this.y = this.canvasHeight; }
    else if (this.y <= 0) { this.yVelocity = -this.yVelocity; this.y = 0; }
  }
}
class Fog {
  constructor({ selector, density = 50, velocity = 2, particle, bgi } = {}) {
    const canvas = document.querySelector(selector);
    const bcr = canvas.parentElement.getBoundingClientRect();
    this.ctx = canvas.getContext('2d');
    this.canvasWidth = canvas.width = bcr.width;
    this.canvasHeight = canvas.height = bcr.height;
    this.particleCount = density;
    this.maxVelocity = velocity;
    this.particle = particle;
    this.bgi = bgi;
    this._createParticles();
    this._setImage();
    if (!this.bgi) return;
    const img = new Image();
    img.onload = () => {
      const size = coverImg(img, this.canvasWidth, this.canvasHeight);
      this.bgi = { img, w: size.w, h: size.h };
      this._render();
    };
    img.src = this.bgi;
  }
  _createParticles() {
    this.particles = [];
    const random = (min, max) => Math.random() * (max - min) + min;
    for (let i = 0; i < this.particleCount; i++) {
      const particle = new FogParticle(this.ctx, this.canvasWidth, this.canvasHeight);
      particle.setPosition(random(0, this.canvasWidth), random(0, this.canvasHeight));
      particle.setVelocity(random(-this.maxVelocity, this.maxVelocity), random(-this.maxVelocity, this.maxVelocity));
      this.particles.push(particle);
    }
  }
  _setImage() {
    if (!this.particle) return;
    const img = new Image();
    img.onload = () => this.particles.forEach(p => p.setImage(img));
    img.src = this.particle;
  }
  _render() {
    if (this.bgi) {
      this.ctx.drawImage(this.bgi.img, 0, 0, this.bgi.w, this.bgi.h);
    } else {
      this.ctx.fillStyle = "rgba(0, 0, 0, 1)";
      this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
    }
    this.particles.forEach(p => p.render());
    requestAnimationFrame(this._render.bind(this));
  }
}
class Eraser {
  constructor({ bgCanvas, brushCanvas, bgi, radius = 120 } = {}) {
    this.bgCanvas = document.querySelector(bgCanvas);
    this.brushCanvas = document.querySelector(brushCanvas);
    this.bgCtx = this.bgCanvas.getContext('2d');
    this.brushCtx = this.brushCanvas.getContext('2d');
    this.parentElement = this.bgCanvas.parentElement;
    const bcr = this.parentElement.getBoundingClientRect();
    this.canvasWidth = this.bgCanvas.width = this.brushCanvas.width = bcr.width;
    this.canvasHeight = this.bgCanvas.height = this.brushCanvas.height = bcr.height;
    this.brushRadius = radius;
    this.bgi = new Image();
    this.bgi.src = bgi;
    this.bgi.onload = this._attachEvents.bind(this);
    const bgCanvasEl = this.bgCanvas;
    this.utils = {
      distanceBetween(point1, point2) {
        return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
      },
      angleBetween(point1, point2) {
        return Math.atan2(point2.x - point1.x, point2.y - point1.y);
      },
      getMousePos(e) {
        const bcr = bgCanvasEl.getBoundingClientRect();
        return { x: e.clientX - bcr.left, y: e.clientY - bcr.top };
      },
      getTouchPos(touch) {
        const bcr = bgCanvasEl.getBoundingClientRect();
        return { x: touch.clientX - bcr.left, y: touch.clientY - bcr.top };
      }
    };
  }
  _attachEvents() {
    const parent = this.parentElement;
    parent.addEventListener('mousemove', this._onMouseMove.bind(this));
    parent.addEventListener('mouseleave', this._onMouseLeave.bind(this));
    parent.addEventListener('touchstart', this._onTouchStart.bind(this), { passive: false });
    parent.addEventListener('touchmove', this._onTouchMove.bind(this), { passive: false });
    parent.addEventListener('touchend', this._onTouchEnd.bind(this), { passive: false });
  }
  _onMouseMove(e) {
    const currentPoint = this.utils.getMousePos(e);
    this._drawStroke(currentPoint);
  }
  _onMouseLeave() { this.lastPoint = null; }
  _onTouchStart(e) {
    e.preventDefault();
    const touch = e.touches[0];
    const pos = this.utils.getTouchPos(touch);
    this.lastPoint = pos;
  }
  _onTouchMove(e) {
    e.preventDefault();
    const touch = e.touches[0];
    const currentPoint = this.utils.getTouchPos(touch);
    this._drawStroke(currentPoint);
  }
  _onTouchEnd(e) {
    e.preventDefault();
    this.lastPoint = null;
  }
  _drawStroke(currentPoint) {
    this.lastPoint = this.lastPoint || currentPoint;
    const dist = this.utils.distanceBetween(this.lastPoint, currentPoint);
    const angle = this.utils.angleBetween(this.lastPoint, currentPoint);
    for (let ii = 0; ii < dist; ii += 5) {
      const x = this.lastPoint.x + (Math.sin(angle) * ii);
      const y = this.lastPoint.y + (Math.cos(angle) * ii);
      const brush = this.brushCtx.createRadialGradient(x, y, 0, x, y, this.brushRadius);
      brush.addColorStop(0, 'rgba(0, 0, 0, 1)');
      brush.addColorStop(0.3, 'rgba(0, 0, 0, 0.1)');
      brush.addColorStop(1, 'rgba(0, 0, 0, 0)');
      this.brushCtx.fillStyle = brush;
      this.brushCtx.fillRect(x - this.brushRadius, y - this.brushRadius, this.brushRadius * 2, this.brushRadius * 2);
    }
    this.lastPoint = currentPoint;
    this.bgCtx.globalCompositeOperation = 'source-over';
    const size = coverImg(this.bgi, this.canvasWidth, this.canvasHeight);
    this.bgCtx.drawImage(this.bgi, 0, 0, size.w, size.h);
    this.bgCtx.globalCompositeOperation = 'destination-in';
    this.bgCtx.drawImage(this.brushCanvas, 0, 0);
  }
}
const coverImg = (img, width, height) => {
  const ratio = img.width / img.height;
  let w = width;
  let h = w / ratio;
  if (h < height) { h = height; w = h * ratio; }
  return { w, h };
};
const bgi = 'https://upforme.ru/uploads/001a/f0/7d/2/35680.webp';
function getFogDensity() {
  if (window.innerWidth < 480) return 25;
  if (window.innerWidth < 768) return 35;
  return 80;
}
function getEraserRadius() {
  if (window.innerWidth < 480) return 40;
  if (window.innerWidth < 768) return 55;
  return 60;
}
function resize() {
  new Fog({ selector: '#fog', particle: 'https://upforme.ru/uploads/001a/f0/7d/2/814636.png', density: getFogDensity(), bgi });
  new Eraser({ bgCanvas: '#fog-bg', brushCanvas: '#brush', radius: getEraserRadius(), bgi });
}
resize();
window.addEventListener("resize", resize);
const customCursor = document.getElementById('brush-cursor');
const fogContainer = document.querySelector('.fog-container');
if (customCursor && fogContainer && window.matchMedia('(pointer: fine)').matches) {
  const updateCursor = (e) => {
    customCursor.style.left = e.clientX + 'px';
    customCursor.style.top = e.clientY + 'px';
    customCursor.style.opacity = '1';
  };
  fogContainer.addEventListener('mousemove', updateCursor);
  fogContainer.addEventListener('mouseenter', () => { customCursor.style.opacity = '1'; });
  fogContainer.addEventListener('mouseleave', () => { customCursor.style.opacity = '0'; });
} else if (customCursor) {
  customCursor.style.display = 'none';
}
document.getElementById('reset-fog')?.addEventListener('click', () => {
  ['fog', 'fog-bg', 'brush'].forEach(id => {
    const canvas = document.getElementById(id);
    if (canvas) {
      const ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
  });
  resize();
});
</script>[/html]

Подпись автора

Функционал форума Книга жалоб Книга предложений Знак зодиака Как вставить видео на форум Форум"Грибные места" Слайдер для картинок Live-box с темами

+1

7

Не, это веселее, конечно же.

Подпись автора

"Я не собираюсь расшифровывать, шиза это или такое чувство юмора. По умолчанию - шиза."(С)

0

8

Галерея фотографий в виде колоды карт

[html]
<div class="cart_container">
  <div class="cart">
    <div class="img-wrap"><img src="https://upforme.ru/uploads/001a/f0/7d/57/591695.jpg" alt="" /></div>
  </div>
  <div class="cart">
    <div class="img-wrap"><img src="https://upforme.ru/uploads/001a/f0/7d/57/865869.jpg" alt="" /></div>
  </div>
  <div class="cart">
    <div class="img-wrap"><img src="https://upforme.ru/uploads/001a/f0/7d/57/492941.jpg" alt="" /></div>
  </div>
  <div class="cart">
    <div class="img-wrap"><img src="https://upforme.ru/uploads/001a/f0/7d/57/119023.jpg" alt="" /></div>
  </div>
  <div class="cart">
    <div class="img-wrap"><img src="https://upforme.ru/uploads/001a/f0/7d/57/961457.jpg" alt="" /></div>
  </div>
  <div class="cart">
    <div class="img-wrap"><img src="https://upforme.ru/uploads/001a/f0/7d/57/502938.jpg" alt="" /></div>
  </div>
</div>

<style>
/*
  📦 Контейнер всей колоды. Позиционируется относительно, чтобы .cart с position: absolute
  были привязаны именно к нему, а не к body.
*/
.cart_container {
  margin: 20px 0;
  position: relative;
}

/*
  🃏 Стиль одной "карты". Все карты наложены друг на друга в центре.
  Высота и ширина фиксированы: 400×300px — это размер "рамки" карты.
*/
.cart {
  height: 400px;
  width: 300px;
  position: absolute;
  top: 0;
  /* Центрирование по горизонтали: 50% экрана минус половина ширины карты (150px) */
  left: calc(50% - 150px);
 
  /*
    ⚠️ ВАЖНО: overflow: visible — чтобы повёрнутые уголки не обрезались!
    Обрезка изображения происходит внутри .img-wrap, а не здесь.
  */
  overflow: visible;
 
  /* Тень и рамка для объёма */
  box-shadow: 0 4px 12px rgba(0,0,0,0.1), 0 10px 20px rgba(0,0,0,0.1);
  cursor: pointer;
  border-radius: 10px; /* Скруглённые углы */
  border: 1px solid #337AB7; /* Синяя рамка */
 
  /*
    🖼️ padding создаёт "паспарту" — фоновую полоску (#BFE2FF) вокруг изображения.
    Без него изображение вплотную прилегает к краю, и скруглённые углы становятся невидимы.
  */
  padding: 10px;
  z-index: 100;
  background-color: #BFE2FF; /* Цвет паспарту */
}

/*
  🌀 Каждой карте задаётся индивидуальный поворот для эффекта "разбросанной колоды".
  У 3-й карты самый сильный поворот (8.5°), поэтому именно у неё чаще всего обрезаются уголки.
*/
.cart:nth-child(1) {
  transform: rotate(-3deg);
  position: relative; /* Только первая карта — relative, чтобы не мешать stacking context */
}
.cart:nth-child(2) { transform: rotate(4deg); }
.cart:nth-child(3) { transform: rotate(8.5deg); } /* ← максимальный поворот */
.cart:nth-child(4) { transform: rotate(-6deg); }
.cart:nth-child(5) { transform: rotate(-2deg); }
.cart:nth-child(6) { transform: rotate(7deg); }

/*
  🖼️ Обёртка для изображения.
  Здесь происходит обрезка изображения, чтобы оно не вылезало за скруглённые углы.
  border-radius чуть меньше (6px), чтобы не касаться синей рамки карты.
*/
.img-wrap {
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 6px;
}

/*
  📸 Изображение внутри карты.
 
  object-fit: cover — масштабирует фото с сохранением пропорций так, чтобы полностью
  заполнить область 300×400px. При этом часть изображения может обрезаться по краям,
  если его пропорции не совпадают с 3:4.
*/
.cart img {
  width: 100%;
  height: 100%;
  /*
   * Режим масштабирования изображения:
   * • cover   — заполняет всю область (может обрезать края, но без пустот) ← используется сейчас
   * • contain — показывает всё изображение (без обрезки, но могут быть пустые полосы)
   * • fill    — растягивает без пустот и обрезки, но искажает пропорции (не рекомендуется)
   */
  object-fit: cover;
  display: block;
}

/*
  🎭 Классы анимации: добавляются при клике.
  bottom — для всех карт, кроме последней в цикле.
  bottom_last — для последней карты (чтобы после неё сбросить порядок).
*/
.bottom {
  z-index: 50;
  animation: move ease-in-out 1s forwards;
}
.bottom_last {
  z-index: 30;
  animation: move_last ease-in-out 1s forwards;
}

/*
  🔄 Анимация "ухода вправо и возврата на место".
  В середине анимации карта сдвигается вправо на 220px (всё ещё внутри контейнера),
  а z-index меняется, чтобы визуально карта уходила "вниз колоды".
*/
@keyframes move {
  0% {
    left: calc(50% - 150px);
    z-index: 150; /* временно поднимаем наверх для плавного старта */
  }
  50% {
    left: calc(50% + 220px); /* улетает вправо */
  }   
  100% {
    left: calc(50% - 150px); /* возвращается на место */
    z-index: 50; /* остаётся внизу колоды */
  }
}
@keyframes move_last {
  0% {
    left: calc(50% - 150px);
    z-index: 150;
  }
  50% {
    left: calc(50% + 220px);
    z-index: 50;
  }   
  100% {
    left: calc(50% - 150px);
    z-index: 30; /* самая нижняя позиция */
  }
}

/*
  📱 Мобильная адаптация: карта становится уже (260px), чтобы повёрнутые края
  не вылезали за границы узкого экрана. Центрирование сохраняется.
*/
@media (max-width: 768px) {
  .cart {
    width: 260px;
    height: calc(260px * 4 / 3);
    left: calc(50% - 130px); /* 260 / 2 = 130 */
  }

  /* Анимации адаптируются под новую ширину */
  @keyframes move {
    0% { left: calc(50% - 130px); z-index: 150; }
    50% { left: calc(50% + 180px); }
    100% { left: calc(50% - 130px); z-index: 50; }
  }
  @keyframes move_last {
    0% { left: calc(50% - 130px); z-index: 150; }
    50% { left: calc(50% + 180px); z-index: 50; }
    100% { left: calc(50% - 130px); z-index: 30; }
  }
}
</style>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(function () {
  let count = 1;      // 🔢 Счётчик кликов (начинается с 1)
  let click = true;   // 🛑 Флаг блокировки повторных кликов во время анимации
  let num = $(".cart").length; // 🃏 Общее количество карт

  $(".cart").click(function() {
    if (!click) return; // Если анимация идёт — игнорируем клик
    click = false;

    // Добавляем нужный класс анимации
    if (count < num) {
      $(this).addClass("bottom");
      count++;
    } else {
      $(this).addClass("bottom_last");
      count++;
    }

    // После полного цикла (6 кликов) — сбрасываем все классы и счётчик
    if (count === num + 1) {
      setTimeout(function () {
        $(".cart").removeClass("bottom bottom_last");
        count = 1;
      }, 1000); 
    }

    // Разблокируем клики через 1 секунду (длительность анимации)
    setTimeout(function () {
      click = true;
    }, 1000);         
  });
});
</script>
[/html]

Подпись автора

Функционал форума Книга жалоб Книга предложений Знак зодиака Как вставить видео на форум Форум"Грибные места" Слайдер для картинок Live-box с темами

0


Вы здесь » kuban-forum.ru - Лучший форум для общения » 🍰Кофейня » ;;;;CSS / JS трюки :)