erikwatson / snowfall.js

Stay cool ☃️
https://erikwatson.github.io/snowfall.js/
MIT License
4 stars 2 forks source link

scheduling #20

Closed erikwatson closed 2 months ago

erikwatson commented 3 years ago

It might be nice to be able to put the snow on a schedule. An example of this might be, only turn the snow on during the month of December. It might also be nice to make that more fine grain - only on Weekends in December between the hours of 6pm and 6am

RaviMauryaHootowl commented 3 years ago

Hey, can I take to add this feature? You could provide me with more specifications.

erikwatson commented 3 years ago

Hi @RaviMauryaHootowl thanks for offering to help. We should talk about it a little.

I think we shouldn't mess with the existing snowfall.start(config) because start should mean start, right now! Instead we could add a function snowfall.schedule(schedule, config), it can just call the regular start function if the date meets the conditions of the schedule config object.

// default snowfall config run only in january and december 
snowfall.schedule({
  months: [1, 12],
})

I think we can just do months for now and it'll be fine, realistically the use case for this is to make it snow on a site during the winter, right? I know I mentioned fine grain control in the first post but probably overkill.

Don't go importing any libs for this, keep it vanilla. What do you think?

RaviMauryaHootowl commented 3 years ago

Ok yes got it. So we can create a separate function schedule for that, which will take schedule along with other configs. Sure I will use Vanilla JS only. So I will start adding this 👍

RaviMauryaHootowl commented 3 years ago

So, this does the work. I have directly used your setDensity function.

function schedule(schedule, config){
  scheduleMonths = schedule.months
  start(config)
  let month = d.getMonth() + 1
  if(!schedule.includes(month)){
    setDensity(0)
  }
}

If you want we can think about some fine controlling (like as the month approaches, snow of less density starts to fall) something like that. What do you think?

erikwatson commented 3 years ago

@RaviMauryaHootowl Setting the density was a good idea, but it's better to just not start snowfall at all unless the date check matches.

I was thinking more along these lines.

const winter = {
  months: [1, 12]
}

function schedule(sch, config=defaultConfig) {
  const d = new Date()
  const month = d.getMonth() + 1

  if (sch.months.includes(month)) {
    start(config)
  }
}

schedule(winter)
RaviMauryaHootowl commented 3 years ago

Yes this seems more efficient. Cool. And what about extra control on that? (Like starting a low density snow as we get close to that month) Or else this much is fine?

erikwatson commented 3 years ago

And what about extra control on that? (Like starting a low density snow as we get close to that month)

I do quite like this idea, but how would it work and how would it be configured?

I think it shouldn't run in the month leading up to the date range, or the one after it, because the user might create ranges where the edges butt up against each other. Instead it should work only on the months specified in the range.

I think we could make it so that the first quarter of the first month, the snowflakes fade in by increasing in density and size until they reach the user specified ones. Then in the fourth quarter of last month of the range, we fade them back out by decreasing size and density in the same way until they reach 0 at the end.

We could just configure it by adding a fadeIn and fadeOut property to the schedule config object, but I am open to suggestions if you have any better ideas.

RaviMauryaHootowl commented 3 years ago

Yes good idea, I was thinking about the same lines. So how about this?

function schedule(sch, config){
  const d = new Date()
  const month = d.getMonth() + 1
  const date = d.getDate()
  scheduleMonths = sch.months
  const fadeInDays = sch.fadeIn
  const fadeOutDays = sch.fadeOut
  // Even if no snowfall this month, atleast set the background
  if (config.bg !== undefined) {
    bg = config.bg
  }

  // fadeIn and fadeOut on endpoints of continuous months
  const monthBefore = (month == 1) ? 12 : month-1
  const monthAfter = (month == 12) ? 1 : month+1
  const lastDateInMonth = daysInMonth(month, d.getFullYear());
  if(scheduleMonths.includes(month)){
    start(config)
    if(date - 1 < fadeInDays && !scheduleMonths.includes(monthBefore)){
      setDensity(density*(date-1)/fadeInDays)
    }else if(date > (lastDateInMonth-fadeOutDays) && !scheduleMonths.includes(monthAfter)){
      setDensity(density*(lastDateInMonth-date)/fadeOutDays)
    }
  }
}

I have used continuous month segments, if December and January is in the input then snow fadesIn at the start of December and fadesOut at the end of January based on the fadeIn and fadeOut configs.

erikwatson commented 3 years ago

I think that looks pretty good at first glance, though of course I have not tested it just yet. There is a lerp function in utils, it might be a good idea to use that when setting the density.

RaviMauryaHootowl commented 3 years ago

Using lerp, do you mean like this?

setDensity(lerp(0, density, (date)/fadeInDays))

Yes I have tested this by changing dates, it works! 💯

erikwatson commented 3 years ago

Yes, that looks good to me. Thanks for taking the time to do this!

Could we also scale the size of the snowflakes up until they reach their maximum size in the same kind of way?

erikwatson commented 3 years ago

I have added an issue to add some UI for this to the visual editor.

Happy to do it myself when we finish up here, but if you are interested, it's just a html page and some JS.

https://github.com/erikwatson/snowfall-editor/issues/1

RaviMauryaHootowl commented 3 years ago

Yes, that looks good to me. Thanks for taking the time to do this!

Could we also scale the size of the snowflakes up until they reach their maximum size in the same kind of way?

For scaling the size of snowflakes according to the schedule, I have thought like this.

let sizeAlpha = 1

function setSizeAlpha(sizeAlphaVal) {
  sizeAlpha = sizeAlphaVal
  restart()
}

During setting the sizeAlpha value

setSizeAlpha((date)/fadeInDays)

Also a line inside makeSnowflakes function needed to be changed according to this method

const size = lerp(3 + Math.random() * 3, 3 + Math.random() * 5, sizeAlpha)

And a line inside the render function (where foreground and background flakes are distinguished)

const bgSize = lerp(5, 7, sizeAlpha)

Let me know if there is any other simple way to do this? Thanks a lot, I am getting to learn a lot from this 😀

erikwatson commented 3 years ago

Let me know if there is any other simple way to do this?

I think that is a little more involved than I had anticipated the code being for this part, you're right that it should be simpler to do something like this.

It really seems to me that we should be able to just pass in an option in the config to the start function that specifies what the base size of a snowflake should be, then we would just be able to set the size in the schedule function. We should be able to just modify the user config with the calculated density and pass it in to the start function like normal too, which would be better than using setDensity() to do it in my opinion.

What I want to be able to write is something like this, but with the calcs, obviously :)

function schedule (sch, config) {
  const isInDateRange = true
  const flakeSize = 2
  const density = 10

  if (isInDateRange) {
    start({ ...config, flakeSize, density })
  }
}

But to get that done we need to modify the start function so it can take a flake size property that gets used in makeSnowflakes(). The size in there would need to be set something like this - const size = flakeSize + Math.random() * 5.

Does that make sense?

erikwatson commented 3 years ago

@RaviMauryaHootowl are you still working on this or should I take over?

RaviMauryaHootowl commented 3 years ago

Hey, sorry for this. I've got a little busy with some personal projects lately. This feature is mostly figured out now. It would be great if you could take over this and complete it. 👍🏻 Thanks a lot for letting me work uptill now, I've learned a lot.

erikwatson commented 3 years ago

No problem, thanks for helping out 😁