如何在SASS中将整数转换为十六进制

5

在SASS中,像Chris Eppstein提到的地图数据结构这样的东西还在进展中,我尝试实现类似的功能——将字符串映射到相应的十六进制值,用于指定CSS content属性的Unicode字符。(我正在重构一些字体图标SASS代码。)

目前我有一个比较基础的实现:

/*icon1  -->  \F000
  icon2  -->  \F001
  icon3  -->  \F002*/

@function u-char($name) {
    @if $name == icon1 {
        @return "000";
    } @else if $name == icon2 {
        @return "001";
    } @else if $name == icon3 {
        @return "001";
    }
}

@mixin icon-class($name) {
    ...
    content: "\f#{u-char($name)}";
    ...
}

但是我实际上正在尝试映射大量字符,因此这种方法很繁琐。我希望能够做到类似以下的操作:

@function u-char($name) {
    $i: 0;
    $itemList: item1, item2, item3;

    @each $currItem in $itemList {
        @if $name == item1 {
            @return i-to-hex-str($i);
        }
        $i: $i + 1;
    }
}

在SASS中是否有将整数转换为十六进制字符串的方法?还有其他优雅的解决方法吗?

5个回答

6
回答你帖子中的最后一个问题,“SASS中是否有将整数转换为十六进制字符串的函数?”。嗯...没有内置函数,但我认为以下代码可以相对清晰地完成这个功能,并且只需要相对较少的代码行数:
/** Returns an at least one byte hex value */
@function dec-to-hex($d) {
    $hexVals: "A" "B" "C" "D" "E" "F";
    $base: 16;
    $quotient: $d;
    $result: "";
    @if $d == 0 {
        $result: "00";
    }
    @while $quotient != 0 {
        $mod: $quotient % $base;
        $quotient: floor($quotient / $base);
        @if $mod > 9 {
            $mod: nth($hexVals, $mod - 9);
        }
        @if $d < $base {
            $result: "0" + $mod;
        } @else {
            $result: $mod + $result;
        }
    }
    @return $result;
}

这段代码并没有在字符串前面添加十六进制限定符(如“0x”或“#”),但是你可以将其硬编码到最后一行中(@return "#" + $result;),或者在调用函数时进行应用。


1
感谢这个函数。很惊讶这样的功能在SASS中还没有内置。 - Prembo
这个回答已经在SASS存储库的此功能请求中被引用。 - luukvhoudt

3

你的帖子中还有一个问题的实现方式:“是否有任何在SASS中将整数转换为十六进制字符串的方法?” 这是一个最短的版本(不适用于最旧的版本,因为可能会缺少 str-slice)。

@function decToHex($dec) {
    $hex: "0123456789ABCDEF";
    $first: (($dec - $dec % 16)/16)+1;
    $second: ($dec % 16)+1;
    @return str-slice($hex, $first, $first) + str-slice($hex, $second, $second)
}

这个答案已经在SASS代码库的这个功能请求中被引用。 - luukvhoudt

2

之前的答案对我们没有用,因此这里提供两个快速函数,可以将整数转换为多种不同的进制,包括十六进制:

@function decimal-to-base($decimal, $to_base, $chars: '0123456789abcdefghijklmnopqrstuvwxyz')
  @if type-of($decimal) != 'number'
    @error '$decimal must be an integer.'
  @if type-of($to_base) != 'number'
    @error '$to-base must be an integer.'
  @if type-of($chars) != 'string'
    @error '$chars must be a string.'
  @if $to_base < 2
    @error '$to-base must be larger than 1.'
  @if $to_base > str-length($chars)
    @error 'Length of $chars must be equal or larger than $to-base.'
  @return _decimal-to-base($decimal, $to_base, $chars)

@function _decimal-to-base($decimal, $to_base, $chars, $_accum: '')
  @if $decimal <= 0
    @return if($_accum != '', $_accum, '0')
  $remainder: $decimal % $to_base
  $char: str-slice($chars, $remainder + 1, $remainder + 1)
  $remaining_decimal: ($decimal - $remainder) / $to_base
  @return _decimal-to-base($remaining_decimal, $to_base, $chars, $char + $_accum)

如果您不关心错误处理,可以跳过第一个函数(它实际上只验证参数并设置默认字符),并复制第二个函数。

另外,请注意这是用SASS编写的,而不是SCSS。要支持SCSS,请添加一些花括号和分号。

示例:

  • 十进制转十六进制:
    decimal-to-base(15731618, 16) // "f00ba2".

  • 十进制转二进制:
    decimal-to-base(34, 2) // "100010".

  • 时间戳转查询字符串:
    decimal-to-base(1547598870, 2) // "pleb0y".

  • 肯定不是莫尔斯电码:
    decimal-to-base(34, 2, '-.') // "-...-.".

  • 过度工程化的整数转字符串:
    decimal-to-base(123456, 10) // "123456".

已知问题:(因为这是一个不完美的实现)

  • 输入的十进制数必须是大于等于0的整数。
  • 最小基数为2。
  • 您需要小心处理大整数。

2

我的功能可以在十六进制和十进制之间转换数字,代码如下:

$hex-chars: "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F";

@function dec-to-hex($d) {
    $result: "";
    $rest: $d;
    @while $rest > 0 {
        $result: nth($hex-chars, $rest % 16 + 1) + $result;
        $rest: floor($rest / 16);
    }
    @return $result;
}

@function pow($number, $exponent) {
    $value: 1;
    @if $exponent > 0 {
        @for $i from 1 through $exponent {
            $value: $value * $number;
        }
    }
    @return $value;
}

@function hex-to-dec($d) {
    $result: 0;
    $number: inspect($d);
    $power: 0;
    @for $index from str-length($number) through 1 {
        $digit: str-slice($number, $index, $index);
        $value: index($hex-chars, $digit) - 1;
        $result: $result + ($value * pow(16, $power) );
        $power: $power + 1;
    }
    @return $result;
}

十进制数被视为数字,而十六进制数被视为字符串。


-1
我会这样做:
$icons: "000", "001", "002";

@function icon($i) {
  @return "\F#{nth($icons, 1)}";
}

h1::before {
  content: icon(1);
}

编辑:

如果您想将一个单词与一个值关联起来,可以尝试使用一个列表的列表并通过迭代它们来实现。我不会假装这很高效,但它是可行的。如果Sass有哈希表就更好了。

$icons: '000' calendar, '001' inbox, '002' home

@function icon($call)
  @for $i from 1 through length($icons)
    @if $call == nth(nth($icons, $i), 2)
      @return "\F#{nth(nth($icons, $i), 1)}"

h1::before
  content: icon(calendar)

我想要实现的是通过mixin能够更加直观地指定图标,只需使用名称即可。例如:font-icon(copyright);。目前,mixin需要您指定名称和相应的Unicode字符,如:font-icon(calendar, "008"); - Prembo
谢谢 - 非常棒的解决方法,考虑到限制条件(即没有Map/Hash)。我喜欢它! - Prembo
我来到这里是因为我在搜索如何在SASS中将整数转换为十六进制,但是这个被接受的答案并没有回答我的问题! - Sorin GFS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接