Javascript-форум (https://javascript.ru/forum/)
-   Javascript под браузер (https://javascript.ru/forum/css-html/)
-   -   Песочные часы (https://javascript.ru/forum/css-html/72671-pesochnye-chasy.html)

wegas 16.02.2018 15:51

Песочные часы
 
если у кого нибудь наработки по данной теме..

j0hnik 16.02.2018 15:58

https://github.com/abrunenko/hourglass

wegas 16.02.2018 16:19

j0hnik,
спасибо, но нужно что то по проще этот код я месяц буду разбирать....

j0hnik 16.02.2018 16:30

Очень просто тут к сожалению не получится, или это будет скрипт вида
js - скрипт меняет раскадровку песочных часов, или еще проще, добавляет на страницу гифку методом appendChild

wegas 21.02.2018 09:52

js - скрипт меняет раскадровку песочных часов, вот на это интересно бы посмотреть))

рони 21.02.2018 12:35

песочные часы animate background-position
 
wegas,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  body{
    background-color: #F6F6F6;
  }

  .slider {
    background-image: url(https://png.pngtree.com/element_origin_min_pic/16/11/24/4f7184d3cd5191b4cdbd63b9c3c4af25.jpg);
     width: 138px;
     height: 300px;
     background-size:  600px 400px;
     background-repeat: no-repeat;
     background-position: 0px -50px;
     margin: 20px auto;
  }

  </style>


</head>

<body>
<div class="slider"></div>
<script>
var n = 0;
(function t() {
  document.querySelector('.slider').style.backgroundPositionX = ((++n%4)* -154)+"px";
  window.setTimeout(t,200)
}());
  </script>
</body>
</html>

j0hnik 21.02.2018 12:48

Рони было бы прикольно rotate 180 между циклами

рони 21.02.2018 12:57

j0hnik,
:) картинку надо подходящую

рони 21.02.2018 13:13

j0hnik,
нет 1 кадра или 2 (песок полностью в одной из колб)
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  body{
    background-color: #F6F6F6;
  }

  .slider {
    background-image: url(https://png.pngtree.com/element_origin_min_pic/16/11/24/4f7184d3cd5191b4cdbd63b9c3c4af25.jpg);
     width: 138px;
     height: 300px;
     background-size:  600px 400px;
     background-repeat: no-repeat;
     background-position: 0px -50px;
     margin: 20px auto;

  }
  .rt{
    transition: transform .9s;
    transform: rotate(180deg);
  }

  </style>


</head>

<body>
<div class="slider"></div>
<script>
var n = 0, el = document.querySelector('.slider'), p = 200;
(function t() {
  if(n == 3) {el.classList.remove("rt"),p = 200};
  n = ++n%4;
  el.style.backgroundPositionX = (-154 * n)+"px";
  if(n == 3) {el.classList.add("rt"),p = 1000};
  window.setTimeout(t,p)
}());
  </script>
</body>
</html>

j0hnik 21.02.2018 18:22

рони,
Но все равно так прикольней

Malleys 22.02.2018 11:24

Рони, это ужасно!!! Но другой картинки не найти! Эта прямо на экране! Я тоже покручу, только на CSS.

<div class="slider"></div>
<style>
.slider {
    background: url(https://png.pngtree.com/element_origin_min_pic/16/11/24/4f7184d3cd5191b4cdbd63b9c3c4af25.jpg)
      0px -50px / 600px 400px
      no-repeat;
      width: 138px;
      height: 300px;
      margin: 20px auto;
      animation: hour-glass-rotation 1.5s infinite, hour-glass-frames 1.5s infinite steps(4);
  }
  
  @keyframes hour-glass-rotation {
    from {
      transform: rotate(180deg);
    }
    
    to {
      transform: rotate(360deg);
    }
  }
  
    @keyframes hour-glass-frames {
    from {
      background-position: 0 -50px;
    }
    
    to {
      background-position: -616px -50px;
    }
  }</style>


Кстати в Unicode есть символ "песочные часы": ⌛⏳⧖⧗

<div class="slider"></div>
<style>

.slider {
  text-align: center;
}
.slider::before {
  content: "\231B";
  font-size: 150px;
  animation: hour-glass 2s infinite;
  display: inline-block;
}

@keyframes hour-glass {
  from, to {
    transform: rotate(0deg);
  }
  
  20%, 40% {
    transform: rotate(-10deg) scale(1.1);
  }
  
  10%, 30% {
    transform: rotate(10deg);
  }
  
  to {
    transform: rotate(1turn) scale(1);
  }
}
</style>


Правда тут нет песка...
Цитата:

Сообщение от j0hnik
Очень просто тут к сожалению не получится

Песок очень просто описывается при помощи блочного клеточного автомата. Если поделить пикселы на блоки 2×2 вертикально и горизонтально, а после каждого шага разделение на блоки сдвигать на один пиксель по горизонтали и вертикали, то все четыре пиксела любого блока оказываются в разных блоках на следующем шаге.

В пикселе может быть песок, а может и не быть. Так что в блоке размером 2×2 возможны 16 состоянии песка... На каждом шаге в этом блоке песок должен падать вниз. Можно ещё описать падение вверх (когда перевёрнуты часы)

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    </head>
    <body>
    	<style>

html {
    background: linear-gradient(#FFFDE7, #E8EAF6);
    height: 100vh;
}

body {
    margin: 0;
    height: 100vh;
    display: flex;
    overflow: hidden;
}

canvas.hour-glass {
    image-rendering: pixelated;
    margin: 1px;
    display: inline-block;
    transition: 500ms;
    border: solid #444;
    border-width: 5px 0;
    margin: auto;
    --transform-scale: scale(2);
    transform: var(--transform-scale, ) var(--transform-rotate, );
    border-radius: 5px;
}

    	</style>
        <script>

class Hourglass {
    constructor(width = 50, height = 75) {
        this.width = width;
        this.height = height;
        this.context = document.createElement("canvas").getContext("2d");

        document.addEventListener("click", this.clickHandler.bind(this));

        let canvas = this.context.canvas;
        canvas.classList.add("hour-glass");
        document.body.appendChild(canvas);

        canvas.width = width;
        canvas.height = height;
        canvas.style.display = "block";

        this.step = 0; /* счётчик итерации */
        this.direction = 0; /* перевёрнуты часы или нет? */
        this.imageData = new ImageData(this.width, this.height);

        this.init();
    }

    init() {
        let data = this.imageData.data;
        let isSand, isEmpty, x, y;

        for (let i = 0, len = data.length; i < len; i += 4) {
            x = i / 4 % this.width;
            y = i / (4 * this.width) | 0;

            /* где песок? */
            isSand = y < .5 * this.height && y > .125 * this.height;

            /* показывает, где не внутренности часов */
            isEmpty = x < this.width * (.5 + .5 * Math.sin((y / this.height - .5) * Math.PI));
            isEmpty ^= x > this.width * (.5 - .5 * Math.sin((y / this.height - .5) * Math.PI));
            isEmpty &= !(x > this.width * .5 - 2 && x < this.width * .5 + 2);

            /* покраска стекла, пустоты и песка */
            data[i + 0] = isEmpty ? 0 : 255 * (.6 + Math.random() / 4);
            data[i + 1] = isEmpty ? 0 : 255 * (.5 + Math.random() / 6);
            data[i + 2] = isEmpty ? 0 : 255 * (.4 + Math.random() / 8);
            data[i + 3] = isEmpty ? 0 : isSand ? 255 : 40;
        }

        this.context.putImageData(this.imageData, 0, 0);

        this.render();
    }

    render() {
        let data = this.imageData.data;
        let a, b, c, d, key;
        let ai, bi, ci, di;

        for (let y = 1 + this.step % 2, h = this.height; y < h; y += 2) {
            for (let x = this.step % 2, w = this.width; x < w; x += 2) {
                /* если не внутренности часов, то идём дальше */
                if (
                    data[ai = 4 * ((x + 0) + (y - 1) * w) + 3] == 0 ||
                    data[bi = 4 * ((x + 1) + (y - 1) * w) + 3] == 0 ||
                    data[ci = 4 * ((x + 0) + (y + 0) * w) + 3] == 0 ||
                    data[di = 4 * ((x + 1) + (y + 0) * w) + 3] == 0 
                ) continue;

                /* смотрим, где песчинки в окрестности 2х2 */
                a = data[ai] != 40 ? 1 : 0;
                b = data[bi] != 40 ? 1 : 0;
                c = data[ci] != 40 ? 1 : 0;
                d = data[di] != 40 ? 1 : 0;

                /* находим их новые местоположения при помощи клеточного автомата  */
                key = ((((((a << 1) | b) << 1) | c) << 1) | d);
                key = Hourglass.CA[key][this.direction];

                data[ai] = (key & 8) == 8 ? 255 : 40;
                data[bi] = (key & 4) == 4 ? 255 : 40;
                data[ci] = (key & 2) == 2 ? 255 : 40;
                data[di] = (key & 1) == 1 ? 255 : 40;
            }
        }

        this.context.putImageData(this.imageData, 0, 0);

        this.step++;

        requestAnimationFrame(this.render.bind(this));
    }

    clickHandler() {
        this.direction = (this.direction + 1) % 2;
        this.context.canvas.style.setProperty("--transform-rotate", "rotate(" + this.direction / 2 + "turn)");
    }
}

/*
правило клеточного автомата
имитирует падение песка
+---+---+
| A | B |
+---+---+
| C | D |
+---+---+
ABCD<i> -> [ABCD<i+1>, ABCD<i-1>]
*/
Hourglass.CA = {
    0b0000: [0b0000, 0b0000],
    0b0001: [0b0001, 0b0100],
    0b0010: [0b0010, 0b1000],
    0b0011: [0b0011, 0b0110],
    0b0100: [0b0001, 0b0100],
    0b0101: [0b0011, 0b1100],
    0b0110: [0b0011, 0b1100],
    0b0111: [0b0111, 0b1101],
    0b1000: [0b0010, 0b1000],
    0b1001: [0b0011, 0b1100],
    0b1010: [0b0011, 0b1100],
    0b1011: [0b1011, 0b1110],
    0b1100: [0b0110, 0b1100],
    0b1101: [0b0111, 0b1101],
    0b1110: [0b1011, 0b1110],
    0b1111: [0b1111, 0b1111]
};

document.addEventListener("DOMContentLoaded", event => {
    new Hourglass();
});

        </script>
    </body>
</html>

рони 22.02.2018 11:45

Цитата:

Сообщение от Malleys
Рони, это ужасно!!!

что ужасно? то что пример был на js, а не на css?
твой пример с песком очень крут, но так песок не падает, он проваливается как бы общей массой и на стенках не должен прилипать.
(это я придираюсь из зависти :) )

рони 26.02.2018 19:10

wegas,
60 * 1000 минута , 4 кадра , время показа одного кадра 60 * 1000 / 4 = 15000.
window.setTimeout(t,15000)

wegas 26.02.2018 19:11

Огромное спасибо... Очень интересные идеи. Все таки на js мне больше нравится, теперь буду думать как привязать это ко времени, чтобы например если идет таймер минута то он корректно отображал эти слайды.... также с часом с днем и тп...
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  body{
    background-color: #F6F6F6;
  }

  .slider {
    background-image: url(http://preview.ibb.co/dTjrsc/7c7008d0eaa571641b1eb3b2af2a6098.png);
     width: 138px;
     height: 270px;
     background-size:  600px 370px;
     background-repeat: no-repeat;
     background-position: 0px -50px;
     margin: 20px auto;
  }

  </style>


</head>

<body>
<div class="slider"></div>
<script>
var n = 0;
(function t() {
  document.querySelector('.slider').style.backgroundPositionX = ((++n%4)* -154)+"px";
  window.setTimeout(t,1000)
}());
  </script>
</body>
</html>

wegas 26.02.2018 19:13

рони,
Спасибо

рони 26.02.2018 19:13

wegas,
прошлый макет был корректным

wegas 26.02.2018 19:20

рони,
я удалил потому что пытаюсь расширить на сайте макет запуска html скрипта. как это сделать???

рони 26.02.2018 19:56

Цитата:

Сообщение от wegas
пытаюсь расширить на сайте макет запуска html скрипта. как это сделать???

не понимаю

wegas 03.03.2018 11:47

рони,
хотел чтобы на сайте этом нормально отображалось без скрола, да ладно не суть важно, спасибо, очень помогли...

рони 03.03.2018 12:07

wegas,
:-?


Часовой пояс GMT +3, время: 11:45.