【问题标题】:Alpine JS: two-way binding converted input values?Alpine JS:双向绑定转换的输入值?
【发布时间】:2023-04-06 09:41:01
【问题描述】:

我正在从一组 HSL 滑块中计算一个十六进制颜色值。

当我更改滑块(通过 x-model 绑定到 HSL 输入)时,十六进制输入会相应更改。

当我试图让它向后工作时,我完全卡住了。

当我在底部输入中输入十六进制值时,如何更改 HSL 值?

https://codesandbox.io/s/agitated-williams-p54t1?file=/index.html

  <body x-data="{h1: h1, s1: s1, l1: l1 }">
    <input type="range" min="0" max="360" step="1" x-model="h1" />
    <input type="number"  min="0" max="360" x-model="h1"/>
    <br>
    <input type="range" min="0" max="100" step="1" x-model="s1" />
    <input type="number"  min="0" max="100" x-model="s1"/>
    <br>
    <input type="range" min="0" max="100" step="1" x-model="l1" />
    <input type="number" min="0" max="100"  x-model="l1"/>
    <br>
    <input type="text" id="hex1" x-bind:value="hslToHex(h1, s1, l1)" />
    <input type="color" id="hex1" x-bind:value="hslToHex(h1, s1, l1)" />
  </body>

  <script>
    var h1 = 50;
    var s1 = 50;
    var l1 = 50;

    function hslToHex(h, s, l) {
        l /= 100;
        const a = s * Math.min(l, 1 - l) / 100;
        const f = n => {
          const k = (n + h / 30) % 12;
          const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
          return Math.round(255 * color).toString(16).padStart(2, '0');   // convert to Hex and prefix "0" if needed
        };
        return myHex = `#${f(0)}${f(8)}${f(4)}`;
    };
  </script>

【问题讨论】:

    标签: alpine.js


    【解决方案1】:

    要使相反的情况正常工作,您首先需要一个 hexToHsl 函数,因为输入将是一个十六进制颜色代码(字符串)。

    我已使用question 来获取将十六进制字符串转换为 HSL 值的函数。

    此外,我已根据documentaionalphine.js 组件逻辑提取到一个函数中,因为它具有更复杂的函数(它是可选的,但最好遵循),其中包含相关数据和函数。

    我已经对文本输入使用了输入事件处理程序,因此它会在给它的任何输入上触发。 (@input="setHSL")

    所以最后,你的组件将如下所示,

    
    <body x-data="app()">
        <input type="range" min="0" max="360" step="1" x-model="h1" />
        <input type="number" min="0" max="360" x-model="h1" />
        <br />
        <input type="range" min="0" max="100" step="1" x-model="s1" />
        <input type="number" min="0" max="100" x-model="s1" />
        <br />
        <input type="range" min="0" max="100" step="1" x-model="l1" />
        <input type="number" min="0" max="100" x-model="l1" />
        <br />
        <input type="text" id="hex-text" @input="setHSL" :value="hslToHex(h1, s1, l1)" />
        <input type="color" id="hex-color" :value="hslToHex(h1, s1, l1)" />
    </body>
    
    <script>
        function app() {
            return {
                h1: 50,
                s1: 50,
                l1: 50,
                setHSL(event) {
                    let hex = event.target.value;
                    // do this only if its a valid hex string
                    if(/^(#)((?:[A-Fa-f0-9]{3}){1,2})$/.exec(hex)){
                        let hsl = this.hexToHsl(hex);
                        this.h1 = hsl.h;
                        this.l1 = hsl.l;
                        this.s1 = hsl.s;
                    }
                },
                hslToHex(h, s, l) {
                    l /= 100;
                    const a = (s * Math.min(l, 1 - l)) / 100;
                    const f = (n) => {
                        const k = (n + h / 30) % 12;
                        const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
                        return Math.round(255 * color)
                            .toString(16)
                            .padStart(2, "0"); // convert to Hex and prefix "0" if needed
                    };
                    return (myHex = `#${f(0)}${f(8)}${f(4)}`);
                },
                hexToHsl(hex) {
                    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    
                    var r = parseInt(result[1], 16);
                    var g = parseInt(result[2], 16);
                    var b = parseInt(result[3], 16);
    
                    r /= 255, g /= 255, b /= 255;
                    var max = Math.max(r, g, b),
                        min = Math.min(r, g, b);
                    var h, s, l = (max + min) / 2;
    
                    if (max == min) {
                        h = s = 0; // achromatic
                    } else {
                        var d = max - min;
                        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
                        switch (max) {
                            case r:
                                h = (g - b) / d + (g < b ? 6 : 0);
                                break;
                            case g:
                                h = (b - r) / d + 2;
                                break;
                            case b:
                                h = (r - g) / d + 4;
                                break;
                        }
                        h /= 6;
                    }
                    s = s * 100;
                    s = Math.round(s);
                    l = l * 100;
                    l = Math.round(l);
                    h = Math.round(360*h);
                    return {h : h, s: s, l:l};
                }
            };
        }
    </script>
    
    
    
    

    在将字符串转换为 HSL 之前,我还进行了额外检查,因为函数可能存在无效输入。所以这里使用的正则表达式只过滤掉十六进制颜色代码。所以转换只会发生在有效输入上。

    【讨论】:

      猜你喜欢
      • 2021-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-17
      • 2015-08-30
      • 2016-08-16
      • 2019-02-17
      相关资源
      最近更新 更多