new_button.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { View, Text } from '@tarojs/components'
  2. import './new_button.scss'
  3. import { rpxToPx } from '@/utils/tools';
  4. import { useState } from 'react';
  5. export enum NewButtonType {
  6. fill = 'fill', //主题实色
  7. alpha = 'alpha', //主题半透明
  8. border = 'border', //主题边框
  9. gray = 'gray', //灰色半透明
  10. text = 'text', //纯文本
  11. link = 'link', //超链接(有可能带icon)
  12. label = 'label',
  13. }
  14. function hexToHSL(hex) {
  15. // 去掉井号,处理3位和6位16进制
  16. hex = hex.replace(/^#/, '');
  17. if (hex.length === 3) {
  18. hex = hex.split('').map(char => char + char).join('');
  19. }
  20. // 解析RGB
  21. const r = parseInt(hex.slice(0, 2), 16) / 255;
  22. const g = parseInt(hex.slice(2, 4), 16) / 255;
  23. const b = parseInt(hex.slice(4, 6), 16) / 255;
  24. // 计算最大和最小值
  25. const max = Math.max(r, g, b);
  26. const min = Math.min(r, g, b);
  27. let h, s, l = (max + min) / 2;
  28. // 计算亮度
  29. if (max === min) {
  30. h = s = 0; // achromatic
  31. } else {
  32. const d = max - min;
  33. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  34. switch (max) {
  35. case r:
  36. h = (g - b) / d + (g < b ? 6 : 0);
  37. break;
  38. case g:
  39. h = (b - r) / d + 2;
  40. break;
  41. case b:
  42. h = (r - g) / d + 4;
  43. break;
  44. }
  45. h /= 6;
  46. }
  47. // 转换为度和百分比
  48. h = Math.round(h * 360);
  49. s = Math.round(s * 100);
  50. l = Math.round(l * 100);
  51. return `hsl(${h}, ${s}%, ${l - 10}%)`;
  52. }
  53. export default function NewButton(props: {
  54. type: NewButtonType,
  55. color?: string,
  56. title?: string,
  57. component?: any,
  58. disable?: boolean,
  59. loading?: boolean,
  60. onClick?: any,
  61. width?: number,
  62. height?: number,
  63. fontSize?: number,
  64. bold?: boolean,
  65. labelBorder?: boolean,
  66. }) {
  67. const [isTouched, setIsTouched] = useState(false)
  68. let style = {}
  69. switch (props.type) {
  70. case NewButtonType.fill:
  71. style = {
  72. height: props.height ?? rpxToPx(72),
  73. width: props.width ?? rpxToPx(198),
  74. borderRadius: props.height ? props.height / 4 : rpxToPx(72 / 4),
  75. backgroundColor: isTouched ? hexToHSL(props.color) : props.disable ? '#B2B2B2' : props.color,
  76. color: '#fff',
  77. fontSize: props.fontSize ?? rpxToPx(30),
  78. display: 'flex',
  79. alignItems: 'center',
  80. justifyContent: 'center',
  81. opacity: props.disable ? 0.6 : 1,
  82. }
  83. break
  84. case NewButtonType.alpha:
  85. style = {
  86. height: props.height ?? rpxToPx(72),
  87. width: props.width ?? rpxToPx(198),
  88. borderRadius: props.height ? props.height / 4 : rpxToPx(72 / 4),
  89. backgroundColor: isTouched ? props.color + '40' : props.disable ? '#B2B2B240' : props.color + '1A',
  90. color: props.disable ? '#b2b2b2' : props.color,
  91. fontSize: props.fontSize ?? rpxToPx(30),
  92. display: 'flex',
  93. alignItems: 'center',
  94. justifyContent: 'center',
  95. opacity: props.disable ? 0.6 : 1,
  96. }
  97. break;
  98. case NewButtonType.border:
  99. style = {
  100. height: props.height ?? rpxToPx(72),
  101. width: props.width ?? rpxToPx(198),
  102. borderWidth: rpxToPx(2),
  103. borderColor: props.disable ? '#B2B2B2' : props.color,
  104. borderStyle: 'solid',
  105. borderRadius: props.height ? props.height / 4 : rpxToPx(72 / 4),
  106. backgroundColor: isTouched ? props.color + '26' : 'transparent',
  107. color: props.disable ? '#b2b2b2' : props.color,
  108. fontSize: props.fontSize ?? rpxToPx(30),
  109. display: 'flex',
  110. alignItems: 'center',
  111. justifyContent: 'center',
  112. opacity: props.disable ? 0.6 : 1,
  113. boxSizing: 'border-box'
  114. }
  115. break;
  116. case NewButtonType.gray:
  117. style = {
  118. height: props.height ?? rpxToPx(72),
  119. width: props.width ?? rpxToPx(198),
  120. borderRadius: props.height ? props.height / 4 : rpxToPx(72 / 4),
  121. backgroundColor: isTouched ? '#b2b2b240' : '#b2b2b210',
  122. color: props.disable ? '#b2b2b2' : '#000000',
  123. fontSize: props.fontSize ?? rpxToPx(30),
  124. display: 'flex',
  125. alignItems: 'center',
  126. justifyContent: 'center',
  127. // opacity: props.disable ? 0.6 : 1,
  128. }
  129. // style = {
  130. // height: props.height ?? rpxToPx(72),
  131. // width: props.width ?? rpxToPx(198),
  132. // borderRadius: props.height ? props.height / 4 : rpxToPx(72 / 4),
  133. // backgroundColor: isTouched ? '#9999991A' : 'transparent',
  134. // color: props.disable ? '#999999' : '#999999',
  135. // fontSize: props.fontSize ?? rpxToPx(30),
  136. // display: 'flex',
  137. // alignItems: 'center',
  138. // justifyContent: 'center',
  139. // // opacity: props.disable ? 0.6 : 1,
  140. // }
  141. break
  142. case NewButtonType.text:
  143. style = {
  144. height: props.height ?? rpxToPx(72),
  145. width: props.width ?? rpxToPx(198),
  146. borderRadius: props.height ? props.height / 4 : rpxToPx(72 / 4),
  147. backgroundColor: props.disable ? '#B2B2B240' : isTouched ? '#B2B2B240' : '#B2B2B21A',
  148. color: props.disable ? '#b2b2b2' : '#000',
  149. fontSize: props.fontSize ?? rpxToPx(30),
  150. display: 'flex',
  151. alignItems: 'center',
  152. justifyContent: 'center',
  153. }
  154. break;
  155. case NewButtonType.link:
  156. style = {
  157. display: 'flex',
  158. alignItems: 'center',
  159. justifyContent: 'center',
  160. flexDirection: 'row',
  161. flex: 1,
  162. color: '#5C7099',
  163. fontSize: rpxToPx(26),
  164. opacity: isTouched ? 0.4 : 1,
  165. }
  166. break
  167. case NewButtonType.label:
  168. style = {
  169. height: rpxToPx(64),
  170. borderRadius: rpxToPx(32),
  171. display: 'flex',
  172. flexDirection: 'row',
  173. alignItems: 'center',
  174. justifyContent: 'center',
  175. fontSize: rpxToPx(28),
  176. paddingLeft: rpxToPx(24),
  177. paddingRight: rpxToPx(24),
  178. boxSizing: 'border-box',
  179. backgroundColor: isTouched ? '#5C709940' : props.labelBorder ? 'transparent' : '#5C70991A',
  180. borderWidth: rpxToPx(2),
  181. borderColor: props.labelBorder ? '#5C709940' : 'transparent',
  182. borderStyle: 'solid',
  183. color: '#5C7099'
  184. }
  185. break
  186. }
  187. return <View
  188. style={{ ...style, fontWeight: props.bold ? 'bold' : 'normal' }}
  189. catchMove
  190. onClick={(e) => {
  191. if (process.env.TARO_ENV == 'weapp') {
  192. e.stopPropagation()
  193. }
  194. if (props.disable) return
  195. props.onClick()
  196. }}
  197. onTouchStart={(e) => {
  198. if (process.env.TARO_ENV == 'weapp') {
  199. e.stopPropagation()
  200. }
  201. if (props.disable) return
  202. setIsTouched(true)
  203. }}
  204. onTouchEnd={(e) => {
  205. if (process.env.TARO_ENV == 'weapp') {
  206. e.stopPropagation()
  207. }
  208. setIsTouched(false)
  209. }}
  210. >{props.component}{props.title}</View>
  211. }