Тестовый

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

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


Вы здесь » Тестовый » Новый форум » Ля-ля-ля Новое


Ля-ля-ля Новое

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

1

ыыыыы

0

2

[html]<div id="watch">
  <div class="frame-face"></div>
  <ul class="minute-marks">
    <!-- li элементы для минутных меток остаются по 48 штук, как в оригинале -->
    <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%);
}

/* Убираем анимации из CSS */
/* @keyframes hours { to {transform:rotate(335deg)} } */
#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:0.4em 6.2em;
  /* transform:rotate(-25deg); Убираем начальный поворот */
  /* animation:hours 43200s linear 0s infinite; Убираем анимацию */
}
#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;
}

/* @keyframes minutes { to {transform:rotate(422deg)} } */
#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:0.4em 11em;
  /* transform:rotate(62deg); Убираем начальный поворот */
  /* animation:minutes 3600s linear 0s infinite; Убираем анимацию */
}

/* @keyframes seconds { to {transform:rotate(480deg)} } */
#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:0.1em 12em;
  /* transform:rotate(120deg); Убираем начальный поворот */
  /* animation:seconds 60s steps(60, end) 0s infinite; Убираем анимацию */
}
#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();
    const hours = now.getHours() % 12;
    const minutes = now.getMinutes();
    const seconds = now.getSeconds();

    // 360 градусов / 12 часов = 30 градусов на час
    const hoursRotation = (hours + minutes / 60) * 30;
    // 360 градусов / 60 минут = 6 градусов на минуту
    const minutesRotation = (minutes + seconds / 60) * 6;
    // 360 градусов / 60 секунд = 6 градусов на секунду
    const 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]

0

3

Туман на фотографии, который убирается курсором мыши

[html]<div class="fog-container">
    <canvas id="fog"></canvas>
    <canvas id="fog-bg"></canvas>
    <canvas id="brush"></canvas>
</div>

<style>
.fog-container {
    aspect-ratio: 16 / 9;
    position: relative;
    overflow: hidden;
    margin: 20px 0;
    border-radius: 6px;
    touch-action: none; /* ← блокирует стандартные жесты (важно для мобильных) */
}
.fog-container canvas {
    display: block;
    width: 100%;
    height: 100%;
    position: absolute;
    left: 50%;
    top: 0;
    transform: translateX(-50%);
}
#brush {
    opacity: 0;
}
/* Мобильные устройства: оставляем на всю ширину */
.fog-container {
    aspect-ratio: 16 / 9;
    position: relative;
    overflow: hidden;
    margin: 20px 0;
    border-radius: 6px;
    touch-action: none;
    width: 100%;
}

/* Десктоп: ограничиваем максимальную ширину */
@media (min-width: 768px) {
    .fog-container {
        max-width: 60rem; /* ≈960px при базовом шрифте 16px */
        /* Или, например: max-width: 80vw; — 80% ширины окна */
        margin-left: auto;
        margin-right: auto;
    }
}
</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 };
};

// ⚠️ Убраны лишние пробелы в URL!
const bgi = 'https://atuin.ru/demo/i/fog-bg.webp';

function resize() {
    // Очистим старые экземпляры при resize (опционально, но полезно)
    new Fog({
        selector: '#fog',
        particle: 'https://atuin.ru/demo/i/fog-particle.png',
        density: 60,
        bgi,
    });
    new Eraser({
        bgCanvas: '#fog-bg',
        brushCanvas: '#brush',
        radius: 80,
        bgi,
    });
}

resize();
window.addEventListener("resize", resize);
</script>[/html]

0

Быстрый ответ

Напишите ваше сообщение и нажмите «Отправить»



Вы здесь » Тестовый » Новый форум » Ля-ля-ля Новое