* Sets `tween.target` to `value` and returns a `Promise` that resolves if and when `tween.current` catches up to it. * * If `options` are provided, they will override the tween's defaults. * @param {T} value * @param {TweenOptions } [options] * @returns
(value, options)
| 236 | * @returns |
| 237 | */ |
| 238 | set(value, options) { |
| 239 | set(this.#target, value); |
| 240 | |
| 241 | let { |
| 242 | delay = 0, |
| 243 | duration = 400, |
| 244 | easing = linear, |
| 245 | interpolate = get_interpolator |
| 246 | } = { ...this.#defaults, ...options }; |
| 247 | |
| 248 | if (duration === 0) { |
| 249 | this.#task?.abort(); |
| 250 | set(this.#current, value); |
| 251 | return Promise.resolve(); |
| 252 | } |
| 253 | |
| 254 | const start = raf.now() + delay; |
| 255 | |
| 256 | /** @type {(t: number) => T} */ |
| 257 | let fn; |
| 258 | let started = false; |
| 259 | let previous_task = this.#task; |
| 260 | |
| 261 | this.#task = loop((now) => { |
| 262 | if (now < start) { |
| 263 | return true; |
| 264 | } |
| 265 | |
| 266 | if (!started) { |
| 267 | started = true; |
| 268 | |
| 269 | const prev = this.#current.v; |
| 270 | |
| 271 | fn = interpolate(prev, value); |
| 272 | |
| 273 | if (typeof duration === 'function') { |
| 274 | duration = duration(prev, value); |
| 275 | } |
| 276 | |
| 277 | previous_task?.abort(); |
| 278 | } |
| 279 | |
| 280 | const elapsed = now - start; |
| 281 | |
| 282 | if (elapsed > /** @type {number} */ (duration)) { |
| 283 | set(this.#current, value); |
| 284 | return false; |
| 285 | } |
| 286 | |
| 287 | set(this.#current, fn(easing(elapsed / /** @type {number} */ (duration)))); |
| 288 | return true; |
| 289 | }); |
| 290 | |
| 291 | return this.#task.promise; |
| 292 | } |
| 293 | |
| 294 | get current() { |
| 295 | return get(this.#current); |