* @param {T} new_value * @param {TweenOptions<T>} [opts]
(new_value, opts)
| 96 | * @param {TweenOptions<T>} [opts] |
| 97 | */ |
| 98 | function set(new_value, opts) { |
| 99 | target_value = new_value; |
| 100 | |
| 101 | if (value == null) { |
| 102 | store.set((value = new_value)); |
| 103 | return Promise.resolve(); |
| 104 | } |
| 105 | |
| 106 | /** @type {Task | null} */ |
| 107 | let previous_task = task; |
| 108 | |
| 109 | let started = false; |
| 110 | let { |
| 111 | delay = 0, |
| 112 | duration = 400, |
| 113 | easing = linear, |
| 114 | interpolate = get_interpolator |
| 115 | } = { ...defaults, ...opts }; |
| 116 | |
| 117 | if (duration === 0) { |
| 118 | if (previous_task) { |
| 119 | previous_task.abort(); |
| 120 | previous_task = null; |
| 121 | } |
| 122 | store.set((value = target_value)); |
| 123 | return Promise.resolve(); |
| 124 | } |
| 125 | |
| 126 | const start = raf.now() + delay; |
| 127 | |
| 128 | /** @type {(t: number) => T} */ |
| 129 | let fn; |
| 130 | task = loop((now) => { |
| 131 | if (now < start) return true; |
| 132 | if (!started) { |
| 133 | fn = interpolate(/** @type {any} */ (value), new_value); |
| 134 | if (typeof duration === 'function') |
| 135 | duration = duration(/** @type {any} */ (value), new_value); |
| 136 | started = true; |
| 137 | } |
| 138 | if (previous_task) { |
| 139 | previous_task.abort(); |
| 140 | previous_task = null; |
| 141 | } |
| 142 | const elapsed = now - start; |
| 143 | if (elapsed > /** @type {number} */ (duration)) { |
| 144 | store.set((value = new_value)); |
| 145 | return false; |
| 146 | } |
| 147 | // @ts-ignore |
| 148 | store.set((value = fn(easing(elapsed / duration)))); |
| 149 | return true; |
| 150 | }); |
| 151 | return task.promise; |
| 152 | } |
| 153 | return { |
| 154 | set, |
| 155 | update: (fn, opts) => |