create.scss 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // #ifdef VUE3 || VUE2 && uniVersion >= 4.56
  2. @use "sass:math";
  3. // #endif
  4. $use-css-var: false !default;
  5. @function div($dividend, $divisor) {
  6. // #ifdef VUE3 || VUE2 && uniVersion >= 4.56
  7. @return math.div($dividend, $divisor);
  8. // #endif
  9. // #ifndef VUE3 || VUE2 && uniVersion >= 4.56
  10. @return $dividend / $divisor;
  11. // #endif
  12. }
  13. // @function to-number($string) {
  14. // $result: 0;
  15. // $is-negative: str-slice($string, 1, 1) == '-';
  16. // $length: str-length($string);
  17. // @if $is-negative {
  18. // $string: str-slice($string, 2);
  19. // $length: $length - 1;
  20. // }
  21. // $decimal-index: str-index($string, '.');
  22. // @if $decimal-index {
  23. // $decimal-str: str-slice($string, $decimal-index + 1);
  24. // $decimal-length: str-length($decimal-str);
  25. // $length: $length - $decimal-length - 1;
  26. // $string: str-slice($string, 1, $decimal-index - 1);
  27. // $result: to-number($decimal-str) * pow(10, $decimal-length * -1);
  28. // }
  29. // $numbers:(
  30. // '0': 0,
  31. // '1': 1,
  32. // '2': 2,
  33. // '3': 3,
  34. // '4': 4,
  35. // '5': 5,
  36. // '6': 6,
  37. // '7': 7,
  38. // '8': 8,
  39. // '9': 9,
  40. // );
  41. // @for $i from 1 through $length {
  42. // $key: str-slice($string, $i, $i);
  43. // $number: map-get($numbers, $key);
  44. // $digit: if($number == 0, 0, if($length - $i > 0, pow(10, $length - $i), 0));
  45. // $result: $result + $digit * $number + if($length - $i == 0, $number, 0);
  46. // }
  47. // @return if($is-negative, $result * -1, $result) ;
  48. // }
  49. // // 由于vue2 h5和app不支持动态rpx 故转成px
  50. // @function rpx-to-px($rpx-string) {
  51. // @if type-of($rpx-string) == list {
  52. // $new-list: ();
  53. // @each $value in $rpx-string {
  54. // $v: $value + '';
  55. // $start: str-index($v, 'rpx');
  56. // @if $start {
  57. // $new-list: append($new-list, rpx-to-px($v));
  58. // } @else {
  59. // $new-list: append($new-list, $value);
  60. // }
  61. // }
  62. // @return $new-list;
  63. // }
  64. // @if type-of($rpx-string) == number and comparable($rpx-string, 1rpx) {
  65. // @return rpx-to-px($rpx-string + '');
  66. // }
  67. // @if type-of($rpx-string) != string {
  68. // @return $rpx-string;
  69. // }
  70. // $start: str-index($rpx-string, 'rpx');
  71. // $number-map: (
  72. // '-': 1,
  73. // '0': 1,
  74. // '1': 1,
  75. // '2': 1,
  76. // '3': 1,
  77. // '4': 1,
  78. // '5': 1,
  79. // '6': 1,
  80. // '7': 1,
  81. // '8': 1,
  82. // '9': 1,
  83. // );
  84. // @if not $start {
  85. // @return $rpx-string;
  86. // }
  87. // $result: '';
  88. // @while $start {
  89. // // 获取 'rpx' 前的数字
  90. // $number-end: $start - 1;
  91. // $number-start: $number-end;
  92. // @while $number-start > 0 and map-get($number-map, str-slice($rpx-string, $number-start, $number-start)) ==1 {
  93. // $number-start: $number-start - 1;
  94. // }
  95. // // 提取数字部分
  96. // $number: to-number(str-slice($rpx-string, $number-start + 1, $number-end));
  97. // // 转换 'rpx' 到 'px'
  98. // // $px-value: ($number / 2) + 'px';
  99. // $px-value: div($number, 2) + 'px';
  100. // $result: $result + str-slice($rpx-string, 0, $number-start) + $px-value;
  101. // // 更新字符串和起始位置
  102. // $rpx-string: str-slice($rpx-string, $start + 3);
  103. // $start: str-index($rpx-string, 'rpx');
  104. // }
  105. // @return $result + $rpx-string;
  106. // }
  107. @function rpx-to-px($value) {
  108. // 递归处理列表
  109. @if type-of($value) == list {
  110. $new-list: ();
  111. @each $item in $value {
  112. $new-list: append($new-list, rpx-to-px($item));
  113. }
  114. @return $new-list;
  115. }
  116. // 处理数字类型 - 带 rpx 单位
  117. @if type-of($value) == number and unit($value) == 'rpx' {
  118. // 安全处理单位转换
  119. @return calc-strip-unit($value) * 0.5 * 1px;
  120. }
  121. // 处理字符串类型
  122. @if type-of($value) == string {
  123. $string: $value;
  124. $rpx-index: str-index($string, 'rpx');
  125. // 如果字符串以数字开头并以 rpx 结尾,转换为数值
  126. @if $rpx-index == (str-length($string) - 2) {
  127. $num-str: str-slice($string, 1, $rpx-index - 1);
  128. $number: to-number($num-str);
  129. @if type-of($number) == number {
  130. @return $number * 0.5 * 1px;
  131. }
  132. }
  133. // 字符串中可能包含多个 rpx 值
  134. @if $rpx-index {
  135. $result: '';
  136. @while $rpx-index {
  137. // 找到数字部分起点
  138. $num-end: $rpx-index - 1;
  139. $num-start: $num-end;
  140. @while $num-start > 0 and is-numeric-char(str-slice($string, $num-start, $num-start)) {
  141. $num-start: $num-start - 1;
  142. }
  143. // 提取数字部分
  144. $num-str: str-slice($string, $num-start + 1, $num-end);
  145. $number: to-number($num-str);
  146. // 转换为 px 数值
  147. $px-value: $number * 0.5 * 1px;
  148. // 构建结果字符串
  149. $result: $result + str-slice($string, 1, $num_start) + '#{$px_value}';
  150. // 更新剩余字符串
  151. $string: str-slice($string, $rpx-index + 3);
  152. $rpx-index: str-index($string, 'rpx');
  153. }
  154. @return #{$result + $string};
  155. }
  156. }
  157. // 其他类型直接返回
  158. @return $value;
  159. }
  160. // 辅助函数:安全去除单位并返回数值
  161. @function calc-strip-unit($number) {
  162. @if type-of($number) == number {
  163. $unit: unit($number);
  164. $units: ("px": 1px, "rpx": 1rpx, "em": 1em, "rem": 1rem, "%": 1%);
  165. @if map-has-key($units, $unit) {
  166. @return div($number , map-get($units, $unit));
  167. }
  168. @if unitless($number) {
  169. @return $number;
  170. }
  171. }
  172. @return $number;
  173. }
  174. // 辅助函数:检查字符是否为数字
  175. @function is-numeric-char($char) {
  176. $chars: "-.0123456789";
  177. @return str-index($chars, $char) != null;
  178. }
  179. // 辅助函数:将字符串安全转换为数字
  180. @function to-number($string) {
  181. // 如果输入已经是数字,直接返回
  182. @if type-of($string) == number {
  183. @return $string;
  184. }
  185. // 处理带符号的数字
  186. $is-negative: false;
  187. $numeric: "";
  188. $found-number: false;
  189. // 提取所有数字字符
  190. @for $i from 1 through str-length($string) {
  191. $char: str-slice($string, $i, $i);
  192. @if $char == "-" and $numeric == "" {
  193. $is-negative: true;
  194. }
  195. @else if $char == "." and str-index($numeric, ".") == null {
  196. $numeric: $numeric + $char;
  197. }
  198. @else if $char >= "0" and $char <= "9" {
  199. $numeric: $numeric + $char;
  200. $found-number: true;
  201. }
  202. }
  203. // 如果有实际数字内容,转换为数值
  204. @if $found-number {
  205. $result: 0;
  206. $decimal-index: str-index($numeric, ".");
  207. @if $decimal-index {
  208. // 处理带小数的数字
  209. $integer-part: str-slice($numeric, 1, $decimal-index - 1);
  210. $decimal-part: str-slice($numeric, $decimal-index + 1);
  211. @if $integer-part == "" { $integer-part: "0"; }
  212. $result: to-integer($integer-part);
  213. $divisor: 1;
  214. @for $i from 1 through str-length($decimal-part) {
  215. $divisor: $divisor * 10;
  216. $digit: to-integer(str-slice($decimal-part, $i, $i));
  217. $result: $result + ($digit / $divisor);
  218. }
  219. } @else {
  220. // 处理整数
  221. $result: to-integer($numeric);
  222. }
  223. @return if($is-negative, -$result, $result);
  224. }
  225. // 无法转换则返回原字符串
  226. @return $string;
  227. }
  228. // 辅助函数:将整数字符串转换为数字
  229. @function to-integer($string) {
  230. $result: 0;
  231. @for $i from 1 through str-length($string) {
  232. $char: str-slice($string, $i, $i);
  233. $result: $result * 10 + (str-index("0123456789", $char) - 1);
  234. }
  235. @return $result;
  236. }
  237. @function create-var($name, $values...) {
  238. // 将不定数量的参数转换为列表
  239. // $use-css-var: false;
  240. // $use-css-var: nth($values, -1) == false;
  241. $value-list: $values;
  242. $css-value: null;
  243. // @if type-of(nth($values, -1)) == bool {
  244. // $use-css-var: nth($values, -1); // 获取布尔值
  245. // // 移除最后一个元素(布尔值)
  246. // $value-list: ();
  247. // @for $i from 1 through (length($values) - 1) {
  248. // $value-list: append($value-list, nth($values, $i));
  249. // }
  250. // }
  251. @if length($value-list) == 0 {
  252. // @warn "The list must have at least 1 values.";
  253. @return '';
  254. } @else {
  255. // 初始化CSS变量的值为列表中的第一个值
  256. /* #ifndef VUE2 */
  257. $css-value: nth($value-list, 1);
  258. /* #endif */
  259. /* #ifdef VUE2 */
  260. $css-value: rpx-to-px(nth($value-list, 1));
  261. /* #endif */
  262. }
  263. // 检查列表长度是否大于等于2
  264. @if length($value-list) >= 2 {
  265. // 使用@for循环遍历剩余的值,并构建CSS变量的完整值
  266. @for $i from 2 through length($value-list) {
  267. /* #ifndef VUE2 */
  268. $css-value: $css-value + ", " + nth($value-list, $i);
  269. /* #endif */
  270. /* #ifdef VUE2 */
  271. $css-value: $css-value + ", " + rpx-to-px(nth($value-list, $i));
  272. /* #endif */
  273. }
  274. }
  275. /* #ifdef UNI-APP-X && APP && uniVersion >= 4.71*/
  276. @if $use-css-var {
  277. @return var(--l-#{$name}, #{$css-value});
  278. } @else {
  279. @return $css-value;
  280. }
  281. /* #endif */
  282. /* #ifndef APP-NVUE || APP-ANDROID || APP-IOS || APP-HARMONY */
  283. @return var(--l-#{$name}, #{$css-value});
  284. /* #endif */
  285. /* #ifdef APP-NVUE || APP-ANDROID || APP-IOS || APP-HARMONY */
  286. @return $css-value;
  287. /* #endif */
  288. }