国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于Taro + React 實(shí)現(xiàn)微信小程序半圓滑塊組件、半圓進(jìn)度條、弧形進(jìn)度條、半圓滑行軌道(附源碼)

這篇具有很好參考價值的文章主要介紹了基于Taro + React 實(shí)現(xiàn)微信小程序半圓滑塊組件、半圓進(jìn)度條、弧形進(jìn)度條、半圓滑行軌道(附源碼)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

效果:

基于Taro + React 實(shí)現(xiàn)微信小程序半圓滑塊組件、半圓進(jìn)度條、弧形進(jìn)度條、半圓滑行軌道(附源碼),Taro,一些例子,taro,react.js,前端,半圓滑軌,半圓進(jìn)度條,弧形進(jìn)度條,半圓滑塊組件

基于Taro + React 實(shí)現(xiàn)微信小程序半圓滑塊組件、半圓進(jìn)度條、弧形進(jìn)度條、半圓滑行軌道(附源碼),Taro,一些例子,taro,react.js,前端,半圓滑軌,半圓進(jìn)度條,弧形進(jìn)度條,半圓滑塊組件

功能點(diǎn):

1、四個檔位

2、可點(diǎn)擊加減切換檔位

3、可以點(diǎn)擊區(qū)域切換檔位

4、可以滑動切換檔位

目的:

給大家提供一些實(shí)現(xiàn)思路,找了一圈,一些文章基本不能直接用,錯漏百出,代碼還藏著掖著,希望可以幫到大家

代碼

ts的寫法風(fēng)格

index.tsx? ? ?

import { View, ITouchEvent, BaseTouchEvent } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { useState } from 'react'
import styles from './index.module.less'
import classNames from 'classnames'
import { debounce } from '~/utils/util'

enum ANGLES {
  ANGLES_135 = -135,
  ANGLES_90 = -90,
  ANGLES_45 = -45,
  ANGLES_0 = 0
}

enum MODE_VALUE {
  MODE_1 = 1,
  MODE_2 = 2,
  MODE_3 = 3,
  MODE_4 = 4
}

const HalfCircle = () => {
  const [state, setState] = useState({
    originAngle: ANGLES.ANGLES_135,
    isTouch: false,
    val: MODE_VALUE.MODE_1,
    originX: 0,
    originY: 0
  })

  /** 半圓的半徑 */
  const RADIUS = 150
  /** 半徑的一半 */
  const RADIUS_HALF = RADIUS / 2
  /** 4/3 圓的直徑 */
  const RADIUS_THIRD = RADIUS_HALF * 3
  /** 直徑 */
  const RADIUS_DOUBLE = RADIUS * 2
  /** 誤差 */
  const DEVIATION = 25

  /** 是否開啟點(diǎn)擊振動 */
  const isVibrateShort = true

  const getAngle = () => {
    return {
      transform: `rotate(${state.originAngle}deg)`,
      transition: `all ${state.isTouch ? ' 0.2s' : ' 0.55s'}`
    }
  }

  /**
   * 根據(jù)坐標(biāo)判斷是否在半圓軌道上,半圓為RADIUS,誤差為DEVIATION
   * @param pageX
   * @param pageY
   */
  const isInHalfCircleLine = (pageX: number, pageY: number, deviation?: number) => {
    const DEVIATION_VALUE = deviation || DEVIATION
    const squareSum = (pageX - RADIUS) * (pageX - RADIUS) + (pageY - RADIUS) * (pageY - RADIUS)
    const min = (RADIUS - DEVIATION_VALUE) * (RADIUS - DEVIATION_VALUE)
    const max = (RADIUS + DEVIATION_VALUE) * (RADIUS + DEVIATION_VALUE)
    return squareSum >= min && squareSum <= max
  }

  /** 根據(jù)做標(biāo)點(diǎn),獲取檔位 0 -> 4, -45 -> 3, -90 -> 2, -135 -> 1,從而獲取旋轉(zhuǎn)的角度 */
  const setGear = (pageX: number, pageY: number) => {
    let val = state.val
    let originAngle = state.originAngle
    if (isInHalfCircleLine(pageX, pageY)) {
      if (pageX > 0 && pageX <= RADIUS_HALF) {
        val = MODE_VALUE.MODE_1
        originAngle = ANGLES.ANGLES_135
      } else if (pageX > RADIUS_HALF && pageX <= RADIUS) {
        val = MODE_VALUE.MODE_2
        originAngle = ANGLES.ANGLES_90
      } else if (pageX > RADIUS && pageX <= RADIUS_THIRD) {
        val = MODE_VALUE.MODE_3
        originAngle = ANGLES.ANGLES_45
      } else {
        val = MODE_VALUE.MODE_4
        originAngle = ANGLES.ANGLES_0
      }
    }

    if (state.val === val) return
    setState((old) => {
      return {
        ...old,
        originAngle,
        val
      }
    })

    if (isVibrateShort) {
      setTimeout(() => {
        Taro.vibrateShort()
      }, 200)
    }
  }

  /**
   * 滑動比較細(xì)膩,根據(jù)x軸坐標(biāo),calcX判斷是否前進(jìn)還是后退
   * @param pageX
   * @param pageY
   */
  const setGearSibler = (pageX: number, pageY: number) => {
    let val = state.val
    let originAngle = state.originAngle
    const calcX = pageX - state.originX
    /** 把誤差值增加,方便滑動 */
    if (isInHalfCircleLine(pageX, pageY, 50)) {
      if (pageX > 0 && pageX <= RADIUS_HALF) {
        if (calcX > 0) {
          /** 向前滑動,就前進(jìn)一個檔位 */
          val = MODE_VALUE.MODE_2
          originAngle = ANGLES.ANGLES_90
        } else {
          /** 向后滑動,就后退一個檔位 */
          val = MODE_VALUE.MODE_1
          originAngle = ANGLES.ANGLES_135
        }
      } else if (pageX > RADIUS_HALF && pageX <= RADIUS) {
        if (calcX > 0) {
          val = MODE_VALUE.MODE_2
          originAngle = ANGLES.ANGLES_90
        } else {
          val = MODE_VALUE.MODE_1
          originAngle = ANGLES.ANGLES_135
        }
      } else if (pageX > RADIUS && pageX <= RADIUS_THIRD) {
        if (calcX > 0) {
          val = MODE_VALUE.MODE_3
          originAngle = ANGLES.ANGLES_45
        } else {
          val = MODE_VALUE.MODE_2
          originAngle = ANGLES.ANGLES_90
        }
      } else {
        if (calcX > 0) {
          val = MODE_VALUE.MODE_4
          originAngle = ANGLES.ANGLES_0
        } else {
          val = MODE_VALUE.MODE_3
          originAngle = ANGLES.ANGLES_45
        }
      }
    }
    setState((old) => {
      return {
        ...old,
        originAngle,
        val
      }
    })
  }

  /**
   * 獲取正確的坐標(biāo)點(diǎn)
   * @param pageX
   * @param pageY
   * @returns
   */
  const getRealXY = (
    pageX: number,
    pageY: number
  ): Promise<{
    realX: number
    realY: number
  }> => {
    return new Promise((resolve) => {
      Taro.createSelectorQuery()
        .select('#sliderBgcId')
        .boundingClientRect((rect) => {
          const { left, top } = rect
          /** 獲取真實(shí)的做標(biāo)點(diǎn) */
          const realX = pageX - left
          const realY = pageY - top
          resolve({
            realX,
            realY
          })
        })
        .exec()
    })
  }

  const onTouchEnd = (event: BaseTouchEvent<any>) => {
    setState((old) => {
      return {
        ...old,
        isTouch: false
      }
    })
  }

  const onTouchMove = debounce(async (event: BaseTouchEvent<any>) => {
    const { pageX, pageY } = event.changedTouches[0]
    const { realX, realY } = await getRealXY(pageX, pageY)
    if (isInHalfCircleLine(realX, realY)) {
      setGearSibler(realX, realY)
    }
  }, 100)

  const onTouchStart = async (event: BaseTouchEvent<any>) => {
    const { pageX, pageY } = event.changedTouches[0]
    const { realX, realY } = await getRealXY(pageX, pageY)
    setState((old) => {
      return {
        ...old,
        originX: realX,
        originY: realY,
        isTouch: true
      }
    })
  }

  /** 點(diǎn)擊設(shè)置檔位 */
  const onHandleFirstTouch = async (event: BaseTouchEvent<any>) => {
    const { pageX, pageY } = event.changedTouches[0]
    const { realX, realY } = await getRealXY(pageX, pageY)
    if (isInHalfCircleLine(realX, realY)) {
      setGear(realX, realY)
    }
  }

  const lose = () => {
    if (state.isTouch) return
    if (state.val === 1) return Taro.showToast({
        title: '最低只能1擋',
        icon: 'error',
        duration: 2000
      })
    setState((old) => {
      return {
        ...old,
        originAngle: state.originAngle - 45,
        val: state.val - 1
      }
    })

    if (isVibrateShort) {
      Taro.vibrateShort()
    }
  }

  const add = () => {
    if (state.isTouch) return
    if (state.val === 4) return Taro.showToast({
        title: '最高只能4擋',
        icon: 'error',
        duration: 2000
      })
    setState((old) => {
      return {
        ...old,
        originAngle: state.originAngle + 45,
        val: state.val + 1
      }
    })

    if (isVibrateShort) {
      Taro.vibrateShort()
    }
  }

  return (
    <View
      className={styles.slider}
      // onTouchEnd={(event) => onTouchEnd(event)}
      // onTouchMove={(event) => onTouchMove(event)}
      // onTouchStart={(event) => onTouchStart(event)}
      onClick={onHandleFirstTouch}
    >
      <View className={styles.activeSliderSet}>
        <View className={styles.activeSlider} style={getAngle()} />
      </View>
      <View className={styles.origin} id="origin">
        <View className={styles.long} style={getAngle()}>
          <View
            className={styles.circle}
            onTouchMove={(event) => onTouchMove(event as BaseTouchEvent<any>)}
            onTouchStart={(event) => onTouchStart(event as BaseTouchEvent<any>)}
            onTouchEnd={(event) => onTouchEnd(event as BaseTouchEvent<any>)}
          />
        </View>
      </View>
      {/* 背景 */}
      <View className={styles.sliderBgc} id="sliderBgcId" />
      {/* 刻度 */}
      {/* <View className={styles.scaleBgc} /> */}
      <View className={styles.centerContent}>
        <View className={styles.centerText}>能量檔位</View>
        <View className={styles.btn_air_bar}>
          <View className={classNames(styles.btn_air, styles.btn_air_left)} onClick={lose}>
            -
          </View>
          <View className={styles.val}>
            <View className="val_text">{state.val}</View>
          </View>
          <View className={classNames(styles.btn_air, styles.btn_air_right)} onClick={add}>
            +
          </View>
        </View>
      </View>
    </View>
  )
}

export default HalfCircle

index.module.less

@color-brand: #EBC795 ;
@borderColor:#706D6D;
@sliderWidth:10px;
@radius:150px;
@long: 150px;
@border-radius: @long;

.slider {
  position: relative;
  padding-bottom: @sliderWidth / 2;
  background-color: #000;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;

  // 背景色
  .sliderBgc {
    width: @long*2;
    height: @long;
    border: @sliderWidth solid;
    border-radius: @border-radius  @border-radius 0 0;
    border-color: @borderColor;
    border-bottom: none;
  }

  .scaleBgc {
    width: @long*2 + @sliderWidth *2;
    height: @long + @sliderWidth;
    position: absolute;
    // bottom: 0;
    // left: 0;
    border: @sliderWidth solid;
    border-radius: @border-radius + @sliderWidth  @border-radius + @sliderWidth 0 0;
    border-color: transparent;
    border-bottom: none;
    top: -10px;
    background-clip: padding-box, border-box;
    background-origin: padding-box, border-box;
    background-image: linear-gradient(to right, #000, #000), linear-gradient(90deg, #FFD1B2, #E49E6B);
  }

  // 激活色
  .activeSliderSet {
    position: absolute;
    width: (@long) *2;
    height: @long;
    // left: 0;
    // bottom: 0;
    z-index: 2;
    overflow: hidden;

    .activeSlider {
      bottom: 0;
      left: 0;
      width: @long*2;
      height: @long;
      border: @sliderWidth solid;
      border-color: @color-brand;
      // border-color: transparent !important;
      border-radius: @border-radius  @border-radius 0 0;
      border-bottom: none;
      transform: rotate(-100deg);
      transform-origin: @long @long;
      // background-clip: padding-box, border-box;
      // background-origin: padding-box, border-box;
      // background-image: linear-gradient(to right, #000, #000), linear-gradient(90deg, #FFD1B2, #E49E6B);
    }
  }

  .origin {
    width: 0;
    height: 0;
    position: absolute;
    background-color: rgba(0, 0, 0, 0.1);
    bottom: 0;
    left: 50%;
    z-index: 11;
    transform: translateX(50%);

    .long {
      width: @long - (@sliderWidth / 2);
      height: 0;
      z-index: 9999;
      position: absolute;
      top: 0;
      left: 0;
      transform-origin: 0 0;
  
      .circle {
        width: 16px;
        height: 16px;
        border-radius: 50%;
        position: absolute;
        top: 50%;
        right: 0;
        transform: translate(50%, -50%);
        background-color: #000;
        border: #fff 4px solid;
        z-index: 999;
        padding: 5px;
      }
    }
  }


}

.centerContent {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 99;
  margin-bottom: 20px;

  .centerText {
    text-align: center;
    color: var(--q-light-color-text-secondary, var(--text-secondary, #8C8C8C));
    font-size: 10px;
    margin-bottom: 25px;
  }

  .btn_air_bar {
    display: flex;
    align-items: center;
  
    .btn_air {
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background-color: wheat;
      font-size: 16px;
      font-weight: 500;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .btn_air_left {
      background-color: #706D6D;
      color: white;
    }

    .btn_air_right {
      background-color: white;
      color: #706D6D;
    }
  
    .val {
      height: 26px;
      display: flex;
      align-items: center;
      margin: 0 30px;
      font-size: 26px;
      font-weight: 700;
    }
  }
} 

防抖的工具函數(shù)debounce 的詳細(xì)代碼:

import { debounce } from '~/utils/util'文章來源地址http://www.zghlxwxcb.cn/news/detail-738645.html

function debounce<T extends Function>(func: T, delay: number): T {
  let timeout
  return function (this: any, ...args: any[]): void {
    const context = this;
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(context, args);
    }, delay);
  } as any;
}

到了這里,關(guān)于基于Taro + React 實(shí)現(xiàn)微信小程序半圓滑塊組件、半圓進(jìn)度條、弧形進(jìn)度條、半圓滑行軌道(附源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 基于 Taro 框架的微信小程序 canvas 繪圖海報組件

    基于 Taro 框架的微信小程序 canvas 繪圖海報組件

    項(xiàng)目需要保存收款碼,效果如圖: (此文僅代表個人日常工作記錄,能力有限描述并不全面) 1.安裝 npm i taro-plugin-canvas -S --production(taro-plugin-canvas 是基于 Taro 框架的微信小程序 canvas 繪圖組件,封裝了常用的操作,通過配置的方式生成分享圖片) ?2.引入:import?{?TaroCanvas

    2024年01月21日
    瀏覽(95)
  • Taro微信小程序 實(shí)現(xiàn)下拉、觸底刷新

    下拉刷新, 需要在頁面的config文件中配置 enablePullDownRefresh: true, onReachBottomDistance: 50, backgroundTextStyle: \\\'dark\\\', 在代碼中使用usePullDownRefresh, 當(dāng)我們刷新頁面時候會觸發(fā)usePullDownRefresh方法,這里我們獲取數(shù)據(jù)。

    2024年02月11日
    瀏覽(29)
  • 微信小程序自定義slider組件實(shí)現(xiàn)雙向滑塊

    微信小程序自定義slider組件實(shí)現(xiàn)雙向滑塊

    實(shí)現(xiàn)效果: zy-slider標(biāo)簽是封裝的自定義組件 我放到了資源這里地址:https://download.csdn.net/download/Axiaoheng_/86399342?spm=1001.2014.3001.5503 wxml引入 參數(shù) 說明 min Number/String slider 最小值 max Number/String slider 最大值 minValue Number/String slider 左邊滑塊初始位置 maxValue Number/String slider 右邊滑塊

    2024年02月10日
    瀏覽(16)
  • Taro:微信小程序通過獲取手機(jī)號實(shí)現(xiàn)一鍵登錄

    ????????本文介紹如果通過微信小程序的getPhoneNumber方法獲取用戶微信綁定的手機(jī)號并自動注冊登錄。 1、按鈕類型 openType 指定 \\\"getPhoneNumber\\\"?? 2、@getphonenumber必須全部小寫 code:手機(jī)號獲取憑證:動態(tài)令牌??赏ㄟ^動態(tài)令牌換取用戶手機(jī)號。 ????????后臺根據(jù)前端傳入

    2024年02月16日
    瀏覽(92)
  • 使用taro+canvas實(shí)現(xiàn)微信小程序的圖片分享功能

    使用taro+canvas實(shí)現(xiàn)微信小程序的圖片分享功能

    二輪充電業(yè)務(wù)中,用戶充電完成后在訂單詳情頁展示訂單相關(guān)信息,用戶點(diǎn)擊分享按鈕喚起微信小程序分享菜單,將生成的圖片海報分享給微信好友或者下載到本地,好友可通過掃描海報中的二維碼加群領(lǐng)取優(yōu)惠。 使用場景及功能:微信小程序 生成海報圖片 分享好友 下載圖

    2024年02月05日
    瀏覽(704)
  • Taro微信小程序?qū)崿F(xiàn) 美團(tuán)購物車小紅點(diǎn)動畫效果
  • 使用taro或react框架的,針對微信小程序隱私協(xié)議的組件封裝,網(wǎng)上找了很久都沒有相關(guān)模版,只有自己寫了一個,現(xiàn)分享給有困難的同伴

    注意:我是使用hooks的,其他可以參考封裝思路大同小異的 首先寫一個PrivacyAgreement.js文件 樣式文件index.scss如下 在需要用到隱私協(xié)議的組件或者api的頁面里面引用

    2024年02月05日
    瀏覽(34)
  • Taro + React + TS + Taro-UI + ECharts + Markdown 開發(fā)微信小程序

    Taro + React + TS + Taro-UI + ECharts + Markdown 開發(fā)微信小程序

    1、安裝 Taro 腳手架工具 npm install -g @tarojs/cli yarn global add @tarojs/cli 2、taro 初始化項(xiàng)目 taro init taro-app 安裝 taro-ui cd taro-app yarn add taro-ui 全局引入taro-ui樣式 3、項(xiàng)目路由路徑 page 對應(yīng)項(xiàng)目路徑 lazyCodeLoading 組件按需注入 Taro.navigateTo({url: xxx}) 小程序內(nèi)部跳轉(zhuǎn) 4、全局添加分享功能

    2024年02月04日
    瀏覽(19)
  • 微信小程序+Taro 混編,Taro 使用微信原生 behaviors

    最近有一個小程序項(xiàng)目,因?yàn)橐恍┰蝽?xiàng)目架構(gòu)選擇了微信小程序原生+Taro 混編的方式進(jìn)行開發(fā),在開發(fā)的過程中發(fā)現(xiàn) Taro 不支持使用原生的 behaviors 特性,因?yàn)榛炀幍脑蝽?xiàng)目當(dāng)中已有原生頁面在使用 behaviors,所以需要一個方案在不影響其他頁面的基礎(chǔ)上使 Taro 也能使用這

    2024年02月11日
    瀏覽(23)
  • 【Taro】微信小程序隱私協(xié)議改造

    ?微信要求小程序開發(fā)者在2023.9.15日前將小程序中調(diào)用獲取用戶隱私api的接口時,都必須要先讓用戶授權(quán),如果用戶拒絕授權(quán),那么小程序的對應(yīng)接口或組件將直接禁用。 那么首先,請將微信小程序開發(fā)者工具-詳情-本地設(shè)置-基礎(chǔ)調(diào)試庫 切換至2.33.0以上。低于該調(diào)試庫會報錯

    2024年02月09日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包