Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 03.01.2013, 10:30
Аватар для Дзен-трансгуманист
√₋̅₁̅
Отправить личное сообщение для Дзен-трансгуманист Посмотреть профиль Найти все сообщения от Дзен-трансгуманист
 
Регистрация: 18.06.2012
Сообщений: 385

Падающий снежок на канвасе :)
Однажды ночью, не так давно, наблюдал очаровательную погоду - стоял не очень сильный мороз, был абсолютный штиль и неспешно присыпал снежок.
И мне захотелось изобразить эту картину в коде.)

Не то чтобы круто, да я и не выпендривался, но может кому-нибудь понравится.
<head>
<style>
img, canvas { position: absolute; left: 0px; top: 0px; margin: 0px; padding: 0px; border: none; }
</style>
<script>

function byId ( id ) {
  return document.getElementById( id );
}

function rand ( min, max ) {
  return Math.random() * ( max - min ) + min;
}

function now () {
  return ( +new Date() ) / 1000;
}

function Sprite ( image, sx, sy, sw, sh, originX, originY ) {

  this.image = image;
  this.sx = sx;
  this.sy = sy;
  this.sw = sw;
  this.sh = sh;
  this.originX = originX ? originX : 0;
  this.originY = originY ? originY : 0;
}

Sprite.prototype.draw = function ( context, x, y, angle, scaleX, scaleY ) {

  context.save();
  context.translate( x, y );
  context.rotate( angle );
  context.scale( scaleX, scaleY );
  context.drawImage(
    this.image,
    this.sx, this.sy,
    this.sw, this.sh,
    -this.originX,
    -this.originY,
    this.sw, this.sh
  );
  context.restore();
}

function Flakes ( canvas, flake, zmin, zmax, count, speed, loopTime ) {

  var viewW = canvas.width;
  var viewH = canvas.height;

  zmax = Math.min( zmax, ( loopTime * speed - flake.height ) / viewH );
  zmin = Math.min( zmin, zmax );

  var particles = [];
  var flakeHalfW = flake.width * 0.5;
  var flakeHalfH = flake.height * 0.5;

  for ( var i = 0; i < count; i++ ) {

    var spawnZ = rand( zmin, zmax );

    particles.push({
      spawnX    : rand( -flakeHalfW / spawnZ, viewW + flakeHalfW / spawnZ ),
      spawnZ    : spawnZ,
      spawnTime : rand( 0, loopTime ),
      speed     : speed / spawnZ,
      halfH     : flakeHalfH / spawnZ
    });
  }

  particles.sort( function ( a, b ) {
    return b.spawnZ - a.spawnZ;
  });

  this.particles = particles;
  this.viewW     = viewW;
  this.viewH     = viewH;
  this.loopTime  = loopTime;
  this.ctx       = canvas.getContext( '2d' );
  this.sprite    = new Sprite(
    flake,
    0, 0,
    flake.width, flake.height,
    flake.width * 0.5, flake.height * 0.5
  );
}

Flakes.prototype.draw = function ( time ) {

  var ctx       = this.ctx;
  var sprite    = this.sprite;
  var particles = this.particles;
  var viewH     = this.viewH;
  var loopTime  = this.loopTime;

  for ( var i = 0; i < particles.length; i++ ) {

    var particle = particles[ i ];
    var y = -particle.halfH + ( ( time + particle.spawnTime ) % loopTime ) * particle.speed;

    if ( y < viewH + particle.halfH ) {
      sprite.draw( ctx, particle.spawnX, y, 0, 1 / particle.spawnZ, 1 / particle.spawnZ );
    }
  }
}

window.onload = function () {

  var imgBg    = byId( 'image-bg' );
  var imgFlake = byId( 'image-flake' );
  var canvas   = byId( 'canvas' );

  document.body.removeChild( imgFlake );

  canvas.width = imgBg.width;
  canvas.height = imgBg.height;

  var ctx = canvas.getContext( '2d' );
  var flakes = new Flakes( canvas, imgFlake, 2, 25, 1500, 400, 30 );

  function render () {

    ctx.clearRect( 0, 0, canvas.width, canvas.height );
    flakes.draw( now() - timeOffset );
  }

  var animate = true;
  var timeStop;
  var timeOffset = 0;
  var intervalId = window.setInterval( render, 40 );

  canvas.onclick = function () {

    if ( animate = !animate ) {
      timeOffset += now() - timeStop;
      intervalId = window.setInterval( render, 40 );
    }
    else {
      timeStop = now();
      window.clearInterval( intervalId );
    }
  }
}

</script>
</head>
<body>
<img id="image-flake" src="http://dl.dropbox.com/u/19390559/share/snowflake.png">
<img id="image-bg" src="http://dl.dropbox.com/u/19390559/share/christmas-tree.png">
<canvas id="canvas"></canvas>
</body>

Можно кликнуть по картинке чтобы остановить/возобновить анимацию.

ps: фон, конечно же, не мой - нашел в гугле.)
__________________

Гейзенберг, возможно, читал этот тред.
Ответить с цитированием
  #2 (permalink)  
Старый 03.01.2013, 12:02
без статуса
Отправить личное сообщение для Deff Посмотреть профиль Найти все сообщения от Deff
 
Регистрация: 25.05.2012
Сообщений: 8,219

Классно!
Сообщение от Дзен-трансгуманист
Можно кликнуть по картинке чтобы остановить/возобновить анимацию.
по идее, чтобы поставить на сайт во всю страницу, не останавливая возможности копирования и ввода текста нун наверно играть с z-index при запуске - остановке.
Ответить с цитированием
  #3 (permalink)  
Старый 03.01.2013, 12:19
sinistral
Посмотреть профиль Найти все сообщения от melky
 
Регистрация: 28.03.2011
Сообщений: 5,418

Сообщение от Дзен-трансгуманист
Не то чтобы круто, да я и не выпендривался, но может кому-нибудь понравится.
классная вещь) осталось добавить сюда рандом в распределение звёздочек, и будет настоящий снегопад
Ответить с цитированием
  #4 (permalink)  
Старый 03.01.2013, 12:48
Профессор
Отправить личное сообщение для DjDiablo Посмотреть профиль Найти все сообщения от DjDiablo
 
Регистрация: 04.02.2011
Сообщений: 1,815

Спасибо порадовал, очень празднично получилось)))

помню когда javascript только только появился все писали телетайп, бегущий строчки, и снегопад. Снежинки правда gif картинками в dom были, тобишь без канваса.

Теперь вот шедевр на канвасе, в следующем году ждём снежинок на webGL )))))
__________________
Лучше калымить в гандурасе чем гандурасить на колыме

Последний раз редактировалось DjDiablo, 03.01.2013 в 12:56.
Ответить с цитированием
  #5 (permalink)  
Старый 03.01.2013, 13:07
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

На этой картинке выглядит хорошо, хотя местами подтормаживает.

А варианты будут, чтобы снежинки полетели вправо, влево, вверх и вбок, вниз и вбок?
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #6 (permalink)  
Старый 03.01.2013, 15:05
Профессор
Отправить личное сообщение для PashPP Посмотреть профиль Найти все сообщения от PashPP
 
Регистрация: 26.07.2012
Сообщений: 281

Красиво, но двадцатню процентов ЦП жрет. Хотя, если останавливать анимацию при открытии другой вкладки - норм. А то задолбал этот снежок, который в фоне на 3 вкладках сжирает все ресурсы.
Ответить с цитированием
  #7 (permalink)  
Старый 03.01.2013, 15:10
без статуса
Отправить личное сообщение для Deff Посмотреть профиль Найти все сообщения от Deff
 
Регистрация: 25.05.2012
Сообщений: 8,219

Сообщение от PashPP
Красиво, но двадцатню процентов ЦП жрет
Хм , в опере 12.12 практически не зависит от числа вкладок, жрет 15% не увеличивая
Ответить с цитированием
  #8 (permalink)  
Старый 03.01.2013, 15:28
Аватар для Дзен-трансгуманист
√₋̅₁̅
Отправить личное сообщение для Дзен-трансгуманист Посмотреть профиль Найти все сообщения от Дзен-трансгуманист
 
Регистрация: 18.06.2012
Сообщений: 385

Сообщение от Deff
поставить на сайт во всю страницу
Не нужно во всю страницу - это будет не анимация, а слайдшоу.)

Сообщение от DjDiablo
в следующем году ждём снежинок на webGL )))))
Ага, если у меня дотянуться руки взяться за спеку, что также влечет за собой изучение OpenGL ES 2.0, а в паузах осваивать соответствующую матчасть да и сами основы 3d, на что уйдет минимум месяц в ускоренном темпе - тогда может быть...))

Сообщение от Gozar
местами подтормаживает
Ну что ж. Спецификация не гарантирует аппаратное ускорение 2d-контекста, но даже если оно и ускорено в некоторых движках, все равно невозможно имеющимися средствами распараллелить отрисовку отдельных спрайтов, мощь железа тут недоступна. Только что померил, каждый кадр содержит 630-670 видимых снежинок, а это уже серьезная цифра с учетом нецелочисленных трансформаций отображения - больше нагрузки на графическую подсистему. К сожалению, тут не разгонишься особенно.

Сообщение от Gozar
А варианты будут, чтобы снежинки полетели вправо, влево, вверх и вбок, вниз и вбок?
А нужно? Ну, я в том смысле, что это тема наподобие "посмотри и порадуйся", я как-то не планировал что-то делать с этим дальше. Поэтому оно в оффтопике.
Оно-то можно сделать и спиральное падение с осевым вращением, и нелинейный ветер с интерполяцией по динамическому векторному полю и зонами турбулентности. Много чего можно сделать. Данное было сделано просто из любопытства - и любопытство я удовлетворил.
__________________

Гейзенберг, возможно, читал этот тред.

Последний раз редактировалось Дзен-трансгуманист, 03.01.2013 в 15:58.
Ответить с цитированием
  #9 (permalink)  
Старый 03.01.2013, 16:40
Аватар для Gozar
Отправить личное сообщение для Gozar Посмотреть профиль Найти все сообщения от Gozar
 
Регистрация: 07.06.2007
Сообщений: 7,504

Сообщение от Дзен-трансгуманист
А нужно?
Тебе, не знаю. Наверное нет.

Прикольно, когда пишешь то, с чем потом можно играться.

Наверное предложение неуместно, раз это в оффтопе?!
__________________
Последний раз редактировалось Gozar, Сегодня в 24:14.
Ответить с цитированием
  #10 (permalink)  
Старый 03.01.2013, 17:04
Профессор
Посмотреть профиль Найти все сообщения от godofjavascript
 
Регистрация: 11.12.2012
Сообщений: 265

годный бенчмарк, как крайсиз 2 прямо
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Падающий снег flame Javascript под браузер 2 03.11.2010 11:25