idlize

Форк
0
63 строки · 2.7 Кб
1
/*
2
 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15

16
import { float64, isFiniteNumber, uint32 } from "@koalaui/common"
17

18
export class EasingSupport {
19
    private x: Float32Array
20
    private y: Float32Array
21

22
    private constructor(size: uint32, xSupplier: (value: float64) => float64, ySupplier: (value: float64) => float64) {
23
        if (!Number.isInteger(size) || size <= 1) throw new Error("easing size must be integer value greater than 1, but is " + size)
24
        this.x = new Float32Array(size)
25
        this.y = new Float32Array(size)
26
        this.x[0] = xSupplier(0)
27
        this.y[0] = ySupplier(0)
28
        const last = size - 1
29
        this.x[last] = xSupplier(1)
30
        this.y[last] = ySupplier(1)
31
        for (let i = 1; i < last; i++) {
32
            const value = i / last
33
            this.x[i] = xSupplier(value)
34
            this.y[i] = ySupplier(value)
35
        }
36
    }
37

38
    convert(value: float64): float64 {
39
        let last = (this.x.length - 1) as uint32
40
        let left = 0 as uint32
41
        if (value < this.x[left]) return this.y[left]
42
        let right = last
43
        if (value > this.x[right]) return this.y[right]
44
        while (left <= right) {
45
            const center = ((left + right) >>> 1) as uint32
46
            if (value < this.x[center]) right = center - 1
47
            else if (value > this.x[center]) left = center + 1
48
            else return this.y[center]
49
        }
50
        return this.y[left > last ? last : left]
51
    }
52

53
    static newCubicBezier(p1x: float64, p1y: float64, p2x: float64, p2y: float64, size: uint32 = 1024): EasingSupport {
54
        if (!isFiniteNumber(p1x) || !isFiniteNumber(p1y) || p1x < 0 || 1 < p1x) throw new Error(`illegal point: (${p1x},${p1y}), where 0 <= x <= 1`)
55
        if (!isFiniteNumber(p2x) || !isFiniteNumber(p2y) || p2x < 0 || 1 < p2x) throw new Error(`illegal point: (${p2x},${p2y}), where 0 <= x <= 1`)
56
        return new EasingSupport(size, (value: float64) => cubicBezierValue(value, p1x, p2x), (value: float64) => cubicBezierValue(value, p1y, p2y))
57
    }
58
}
59

60
function cubicBezierValue(left: float64, p1: float64, p2: float64): float64 {
61
    const right = 1 - left
62
    return left * (3 * right * (p1 * right + p2 * left) + left * left)
63
}
64

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.