new_button.tsx 13 KB

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