new_button.tsx 13 KB

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