new_button.tsx 11 KB

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