Leon 2 anos atrás
pai
commit
824f8b87a6

+ 2 - 1
src/app.config.ts

@@ -1,7 +1,8 @@
 const appConfig = defineAppConfig({
   pages: [
-    'pages/demo',
     'pages/Clock',
+    'pages/demo',
+    
     'pages/index/index',
     'pages/Login',
     'pages/Auth',

+ 1 - 0
src/assets/svg/minus.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><g><g></g><g><rect x="4" y="9" width="12" height="2" rx="1" fill="#AAFF00" fill-opacity="1"/></g></g></svg>

+ 0 - 0
src/assets/svg/placeholder


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/svg/plus.svg


+ 21 - 0
src/components/Stepper.scss

@@ -0,0 +1,21 @@
+.stepper_bg{
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    background-color: #000;
+}
+
+.stepper_icon{
+    width: 30px;
+    height: 30px;
+}
+
+.stepper_item{
+    background-color: #1c1c1c;
+    width: 72px;
+    height: 72px;
+    border-radius: 36px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}

+ 65 - 0
src/components/Stepper.tsx

@@ -0,0 +1,65 @@
+import { View, Image } from "@tarojs/components";
+import minus from '../assets/svg/minus.svg'
+import plus from '../assets/svg/plus.svg'
+import './Stepper.scss'
+import { useEffect, useState } from "react";
+
+export default function Component(props: { child: any, minus: Function, plus: Function, disableMinus?: boolean, disablePlus?: boolean }) {
+    const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);
+    useEffect(()=>{
+        if(props.disableMinus){
+            timer && clearInterval(timer);
+        }
+        if(props.disablePlus){
+            timer && clearInterval(timer);
+
+        }
+    },[props.disableMinus,props.disablePlus])
+
+
+    function tapMinus() {
+        props.minus();
+    }
+
+    function tapPlus() {
+        props.plus();
+    }
+    function longMinus() {
+        const newTimer = setInterval(() => {
+            props.minus();
+        },200);
+        setTimer(newTimer)
+    }
+
+    function longPlus() {
+        const newTimer = setInterval(() => {
+            props.plus();
+        },200);
+        setTimer(newTimer)
+    }
+
+    function longMinusEnd(){
+        if (timer)
+            clearInterval(timer);
+        setTimer(null);
+    }
+
+    function longPlusEnd(){
+        if (timer)
+            clearInterval(timer);
+        setTimer(null);
+    }
+    return <View className="stepper_bg">
+        <View className="stepper_item" onClick={tapMinus} onLongPress={longMinus} onTouchEnd={longMinusEnd}>
+            <Image src={minus} className="stepper_icon" />
+        </View>
+
+        {
+            props.child
+        }
+        <View className="stepper_item" onClick={tapPlus} onLongPress={longPlus} onTouchEnd={longPlusEnd}>
+            <Image src={plus} className="stepper_icon" />
+        </View>
+
+    </View>
+}

+ 15 - 14
src/features/trackTimeDuration/components/Console.tsx

@@ -11,6 +11,7 @@ import { endFast, endSleep, startFast, startSleep } from "../actions/TrackTimeAc
 import { durationDatas, durationIndex, pickerDurations } from "../hooks/Console";
 import PickerViews from "@/components/PickerViews";
 import Modal from "@/components/Modal";
+import Stepper from "@/components/Stepper";
 
 export default function Component() {
     const [key, setKey] = useState('');
@@ -26,8 +27,8 @@ export default function Component() {
     const [sleepStr, setSleepStr] = useState('00:00');
     const [isOpen, setIsOpen] = useState(false);
     const [showModal, setShowModal] = useState(false);
-    const [fastPickerValue, setFastPickerValue] = useState([0,0])
-    const [sleepPickerValue, setSleepPickerValue] = useState([0,0])
+    const [fastPickerValue, setFastPickerValue] = useState([0, 0])
+    const [sleepPickerValue, setSleepPickerValue] = useState([0, 0])
     const [isOpenDurationPicker, setIsOpenDurationPicker] = useState(false)
 
     // const [pickerValue, setPickerValue] = useState([0,0])
@@ -135,7 +136,7 @@ export default function Component() {
         var current_record = machine.context.checkData ? (machine.context.checkData as any).current_record : null;
         if (current_record && current_record.last_real_check_time)
             limit = current_record.last_real_check_time
-        return <View style={{backgroundColor:'#fff'}}>
+        return <View style={{ backgroundColor: '#fff' }}>
             <LimitPickers limit={limit} limitDay={7} onCancel={hidePicker} onChange={(e) => {
                 console.log(new Date(e))
                 pickerConfirm(e)
@@ -206,9 +207,9 @@ export default function Component() {
     };
 
     function durationChange(e) {
-        var count = (e[0]+common.duration.min)*60+e[1]*common.duration.step
+        var count = (e[0] + common.duration.min) * 60 + e[1] * common.duration.step
         isFast ? setFastDuration(count * 60000) : setSleepDuration(count * 60000);
-        isFast?setFastPickerValue(e):setSleepPickerValue(e)
+        isFast ? setFastPickerValue(e) : setSleepPickerValue(e)
 
         setIsOpenDurationPicker(false)
     }
@@ -248,10 +249,10 @@ export default function Component() {
         </View>
     }
 
-    
+
     function durationPickerContent() {
-        return <View style={{ color: '#000',backgroundColor:'#fff' }}>
-            <PickerViews onChange={durationChange} items={durationDatas(common)} value={isFast?fastPickerValue:sleepPickerValue} height={200} showBtns={true} onCancel={() => { setIsOpenDurationPicker(false) }} />
+        return <View style={{ color: '#000', backgroundColor: '#fff' }}>
+            <PickerViews onChange={durationChange} items={durationDatas(common)} value={isFast ? fastPickerValue : sleepPickerValue} height={200} showBtns={true} onCancel={() => { setIsOpenDurationPicker(false) }} />
         </View>
     }
     return (
@@ -270,10 +271,10 @@ export default function Component() {
                 </View>
             }
             {
-                (value == 'ONGOING1' || value == 'WAIT_FOR_START') &&
-                <Text style={{marginBottom:10}} onClick={showDurationPicker}>时长:{durationFormate()}</Text>
-                // <PickerViews onChange={durationChange} items={[pickerDurations()]} value={isFast ? [fastPickerValue] : [sleepPickerValue]} />
-                // <TimePickers time={isFast ? fastStr : sleepStr} content="" change={handlePickerChange} isPickerView={true} />
+                (value == 'ONGOING1' || value == 'WAIT_FOR_START') && <Stepper style={{ marginBottom: 10 }} child={
+                    <Text  onClick={showDurationPicker}>时长:{durationFormate()}</Text>
+                } minus={() => { console.log('minus')}} plus={() => {console.log('plus') }} disableMinus={false} disablePlus={false} />
+                // <Text style={{marginBottom:10}} onClick={showDurationPicker}>时长:{durationFormate()}</Text>
             }
             {
                 machine.context.checkData && value == 'ONGOING2' && <View>
@@ -299,10 +300,10 @@ export default function Component() {
                 }
             </View>
             {
-                showModal && isOpen && <Modal children={layoutContent()} dismiss={()=>setIsOpen(false)}/>
+                showModal && isOpen && <Modal children={layoutContent()} dismiss={() => setIsOpen(false)} />
             }
             {
-                isOpenDurationPicker && <Modal children={durationPickerContent()} dismiss={()=>setIsOpenDurationPicker(false)}/>
+                isOpenDurationPicker && <Modal children={durationPickerContent()} dismiss={() => setIsOpenDurationPicker(false)} />
             }
 
             {/* {

+ 87 - 167
src/pages/demo.tsx

@@ -20,8 +20,10 @@ export default function Demo() {
 
   var currentContext;
 
-  var startAngle,endAngle;
+  var startAngle = 45*Math.PI/180;
+  var endAngle = 120*Math.PI/180;
   var lastAngle;
+  var lastDuration = 0;
 
   useEffect(() => {
 
@@ -51,43 +53,39 @@ export default function Demo() {
     const centerY = canvasHeight / 2;
     const radius = Math.min(centerX, centerY) - 10;
 
+
+
+    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+      
+
     ctx.beginPath();
     ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
     ctx.strokeStyle = "rgba(0,0,0,0.5)";
     ctx.lineWidth = 10;
     ctx.stroke();
 
-    // 绘制绿色起点圆点
-    const pointAngle = 45; // 圆环上的角度
-    const pointX = centerX + Math.cos((pointAngle * Math.PI) / 180) * radius;
-    const pointY = centerY + Math.sin((pointAngle * Math.PI) / 180) * radius;
-
-    // 绘制蓝色终点圆点
-    const pointEndAngle = 120; // 圆环上的角度
-    const pointEndX = centerX + Math.cos((pointEndAngle * Math.PI) / 180) * radius;
-    const pointEndY = centerY + Math.sin((pointEndAngle * Math.PI) / 180) * radius;
-
-    startAngle = (pointAngle * Math.PI) / 180;
-    endAngle = (pointEndAngle * Math.PI) / 180;
-
     ctx.beginPath();
     ctx.arc(centerX, centerY, radius, startAngle, endAngle);
     ctx.strokeStyle = canRingDrag?"red":"rgba(255,0,0,0.5)";
     ctx.lineWidth = 10;
     ctx.stroke();
 
+    const pointX = centerX + Math.cos(startAngle) * radius;
+    const pointY = centerY + Math.sin(startAngle) * radius;
 
     ctx.beginPath();
     ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
     ctx.fillStyle = '#00ff00';
     ctx.fill();
 
-    
 
-    
+
+    // 绘制蓝色终点圆点
+    const pointX2 = centerX + Math.cos(endAngle) * radius;
+    const pointY2 = centerY + Math.sin(endAngle) * radius;
 
     ctx.beginPath();
-    ctx.arc(pointEndX, pointEndY, 5, 0, 2 * Math.PI);
+    ctx.arc(pointX2, pointY2, 5, 0, 2 * Math.PI);
     ctx.fillStyle = 'blue';
     ctx.fill();
   };
@@ -97,67 +95,96 @@ export default function Demo() {
     return dep;
   }
 
+  function limitAngle(start,end) {
+    var angle1 = start<0?start+2*Math.PI:start;
+    var angle2 = end<0?end+2*Math.PI:end;
+    if (angle2<angle1){
+      angle2 = angle2+2*Math.PI;
+    }
+
+    var leftAngle = angle2-angle1;
+    if (leftAngle>Math.PI*23/12){
+      return 1;
+    }
+    else if (leftAngle<Math.PI/12){
+      return 2;
+    }
+    return 0;
+  }
+
+  function durationAngle(end,start) {
+    var angle1 = start<0?start+2*Math.PI:start;
+    var angle2 = end<0?end+2*Math.PI:end;
+    if (angle2<angle1){
+      angle2 = angle2+2*Math.PI;
+    }
+
+    return angle2-angle1;
+  }
+
   const handleTouchMove = (e: any) => {
+    const ctx = currentContext;//canvasRef.current.getContext('2d');
     if (!canStartDrag && !canEndDrag && !canRingDrag){
+      drawCanvas(ctx);
       return;
     }
-    const ctx = currentContext;//canvasRef.current.getContext('2d');
-    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+    
     const { x, y } = e.touches[0];
 
-    const centerX = canvasWidth / 2;
-    const centerY = canvasHeight / 2;
-    const radius = Math.min(centerX, centerY) - 10;
-
     let angle = Math.atan2(y-canvasWidth/2.0, x-canvasWidth/2.0)
 
     if (canStartDrag){
-      startAngle = angle;
+      if (Math.abs(durationAngle(endAngle,angle)-lastDuration)>Math.PI){
+        //禁止跨越
+        return;
+      }
+
+      var result = limitAngle(angle,endAngle);
+      switch (result){
+        case 0:
+          startAngle = angle;
+          break;
+        case 1:
+          startAngle = endAngle-23*Math.PI/12;
+          break;
+        case 2:
+          startAngle = endAngle-Math.PI/12;
+          break;
+      }
+      
     }
 
     if (canEndDrag){
-      endAngle = angle;
+      if (Math.abs(durationAngle(angle,startAngle)-lastDuration)>Math.PI){
+        //禁止跨越
+        return;
+      }
+
+      var result = limitAngle(startAngle,angle);
+      switch (result){
+        case 0:
+          endAngle = angle;
+          break;
+        case 1:
+          endAngle = startAngle+23*Math.PI/12;
+          break;
+        case 2:
+          endAngle = startAngle+Math.PI/12;
+          break;
+      }
+      
     }
 
     if (canRingDrag){
-      console.log(`lastAngle:${lastAngle}  angle:${angle}`)
       let delta = angle - lastAngle;
       startAngle += delta;
       endAngle += delta;
       lastAngle = angle;
     }
-      
-
-    ctx.beginPath();
-    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
-    ctx.strokeStyle = "rgba(0,0,0,0.5)";
-    ctx.lineWidth = 10;
-    ctx.stroke();
-
-    ctx.beginPath();
-    ctx.arc(centerX, centerY, radius, startAngle, endAngle);
-    ctx.strokeStyle = canRingDrag?"red":"rgba(255,0,0,0.5)";
-    ctx.lineWidth = 10;
-    ctx.stroke();
-
-    const pointX = centerX + Math.cos(startAngle) * radius;
-    const pointY = centerY + Math.sin(startAngle) * radius;
 
-    ctx.beginPath();
-    ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
-    ctx.fillStyle = '#00ff00';
-    ctx.fill();
-
-
-
-    // 绘制蓝色终点圆点
-    const pointX2 = centerX + Math.cos(endAngle) * radius;
-    const pointY2 = centerY + Math.sin(endAngle) * radius;
+    drawCanvas(ctx);
 
-    ctx.beginPath();
-    ctx.arc(pointX2, pointY2, 5, 0, 2 * Math.PI);
-    ctx.fillStyle = 'blue';
-    ctx.fill();
+    lastDuration = durationAngle(endAngle,startAngle);
   };
 
   const handleClick = (e) => {
@@ -166,9 +193,6 @@ export default function Demo() {
     const scaleY = 1//dpr//canvasRect.height / canvasRect.height;
     const canvasX = (e.touches[0].x - 0) * scaleX;
     const canvasY = (e.touches[0].y - 0) * scaleY;
-    console.log(`x:${canvasX}  y:${canvasY}`)
-
-    // const ctx = canvasRef.current.getContext('2d');
 
     // 判断点击位置是否在圆点范围内
     const centerX = canvasWidth / 2;
@@ -180,7 +204,7 @@ export default function Demo() {
     const pointY = centerY + Math.sin(startAngle) * radius;
     const distance = Math.sqrt(Math.pow(canvasX - pointX, 2) + Math.pow(canvasY - pointY, 2));
 
-    if (distance <= 5) {
+    if (distance <= 8) {
       canStartDrag = true;
     } else {
       canStartDrag = false;
@@ -190,7 +214,7 @@ export default function Demo() {
     const pointY2 = centerY + Math.sin(endAngle) * radius;
     const distance2 = Math.sqrt(Math.pow(canvasX - pointX2, 2) + Math.pow(canvasY - pointY2, 2));
 
-    if (distance2 <= 5) {
+    if (distance2 <= 8) {
       canEndDrag = true;
     } else {
       canEndDrag = false;
@@ -205,17 +229,16 @@ export default function Demo() {
     let angle = Math.atan2(canvasY-canvasWidth/2.0, canvasX-canvasWidth/2.0)
     if (distance3>80&& distance3<105 && startAngle<angle && angle<endAngle){
       canRingDrag = true;
-      console.log("canRingDrag")
     }
-    console.log(distance3);
     lastAngle = angle;
+
+    drawCanvas(currentContext);
   };
 
   const handleTouchEnd = (e) =>{
     canStartDrag = false;
     canEndDrag = false;
     canRingDrag = false;
-    console.log('end')
     handleTouchMove(e)
   }
 
@@ -228,106 +251,3 @@ export default function Demo() {
       ref={canvasRef} />
   </View>
 }
-
-// const CircleCanvas = () => {
-//   const canvasRef = useRef<any>(null);
-//   const canvasWidth: number = 200;
-//   const canvasHeight: number = 200;
-//   const circleRadius: number = 100;
-//   const ringWidth: number = 30;
-//   const dotRadius: number = 10;
-//   const dpr = Taro.getSystemInfoSync().pixelRatio; // 获取设备的像素比
-
-//   useEffect(() => {
-//     const query = Taro.createSelectorQuery();
-//     query.select('.111').fields({ node: true, size: true });
-//     query.exec((res) => {
-//       if (res[0] == null) return;
-//       const _canvas = res[0].node;
-//       _canvas.width = res[0].width * dpr;
-//       _canvas.height = res[0].height * dpr;
-//       const ctx = _canvas.getContext('2d');
-
-//       // const center = radius + lineWidth / 2; // 圆心坐标
-//       // ctx.clearRect(0, 0, radius * 2, radius * 2); // 清除画布
-
-//       // 设置画布尺寸
-//       ctx.scale(dpr, dpr);
-
-
-//       drawCanvas(ctx);
-//     });
-//   }, []);
-
-//   const drawCanvas = (context: any) => {
-//     context.clearRect(0, 0, canvasWidth, canvasHeight);
-
-//     // 绘制红色圆环
-//     context.beginPath();
-//     context.arc(
-//       canvasWidth / 2,
-//       canvasHeight / 2,
-//       circleRadius,
-//       0,
-//       2 * Math.PI,
-//       false
-//     );
-//     context.lineWidth = ringWidth;
-//     context.strokeStyle = 'red';
-//     context.stroke();
-
-//     // 绘制绿色圆点
-//     context.beginPath();
-//     context.arc(
-//       canvasWidth / 2,
-//       canvasHeight / 2,
-//       dotRadius,
-//       0,
-//       2 * Math.PI,
-//       false
-//     );
-//     context.fillStyle = 'green';
-//     context.fill();
-//   };
-
-//   const handleTouchMove = (e: any) => {
-//     const context = canvasRef.current.getContext('2d');
-//     const { x, y } = e.touches[0];
-//     drawCanvas(context);
-
-//     // 绘制拖动后的红色圆环
-//     context.beginPath();
-//     context.arc(x, y, circleRadius, 0, 2 * Math.PI, false);
-//     context.lineWidth = ringWidth;
-//     context.strokeStyle = 'red';
-//     context.stroke();
-
-//     // 绘制绿色圆点
-//     context.beginPath();
-//     context.arc(x, y, dotRadius, 0, 2 * Math.PI, false);
-//     context.fillStyle = 'green';
-//     context.fill();
-//   };
-
-//   return <View>
-//     <Canvas canvasId='111' id='111' className='111' type="2d"
-//       style={{ width: 400, height: 400, zIndex: 0 }}
-//       onTouchMove={handleTouchMove}
-//       onTouchEnd={drawCanvas}
-//       ref={canvasRef} />
-//   </View>
-
-
-//   // return (
-//   //   <View className='circle-canvas'>
-//   //     <canvas
-//   //       ref={canvasRef}
-//   //       style={`width: ${canvasWidth}px; height: ${canvasHeight}px;`}
-//   //       onTouchMove={handleTouchMove}
-//   //       onTouchEnd={drawCanvas}
-//   //     />
-//   //   </View>
-//   // );
-// };
-
-// export default CircleCanvas;

+ 299 - 0
src/pages/demo_backup.tsx

@@ -0,0 +1,299 @@
+import Taro from '@tarojs/taro';
+import { Canvas, View } from '@tarojs/components';
+import { useEffect, useRef } from 'react';
+
+export default function Demo() {
+  const canvasRef = useRef<any>(null);
+  const canvasWidth: number = 200;
+  const canvasHeight: number = 200;
+  const circleRadius: number = 100;
+  const ringWidth: number = 30;
+  const dotRadius: number = 10;
+  const dpr = Taro.getSystemInfoSync().pixelRatio; // 获取设备的像素比
+
+  const canvasId = 'canvasId';
+
+  var canDrag = false;
+  var canStartDrag = false;
+  var canEndDrag = false;
+  var canRingDrag = false;
+
+  var currentContext;
+
+  var startAngle = 45*Math.PI/180;
+  var endAngle = 120*Math.PI/180;
+  var lastAngle;
+  var lastDuration = 0;
+
+  useEffect(() => {
+
+    const query = Taro.createSelectorQuery();
+    query.select(`.${canvasId}`).fields({ node: true, size: true });
+    query.exec((res) => {
+      if (res[0] == null) return;
+      const _canvas = res[0].node;
+      _canvas.width = res[0].width * dpr;
+      _canvas.height = res[0].height * dpr;
+      const ctx = _canvas.getContext('2d');
+      currentContext = ctx;
+
+      // 设置画布尺寸
+      ctx.scale(dpr, dpr);
+
+
+      drawCanvas(ctx);
+    });
+  }, []);
+
+  const drawCanvas = (ctx: any) => {
+    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+
+    // 绘制圆环
+    const centerX = canvasWidth / 2;
+    const centerY = canvasHeight / 2;
+    const radius = Math.min(centerX, centerY) - 10;
+
+    ctx.beginPath();
+    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
+    ctx.strokeStyle = "rgba(0,0,0,0.5)";
+    ctx.lineWidth = 10;
+    ctx.stroke();
+
+    // 绘制绿色起点圆点
+    const pointX = centerX + Math.cos(startAngle) * radius;
+    const pointY = centerY + Math.sin(startAngle) * radius;
+
+    // 绘制蓝色终点圆点
+    const pointEndX = centerX + Math.cos(endAngle) * radius;
+    const pointEndY = centerY + Math.sin(endAngle) * radius;
+
+
+    ctx.beginPath();
+    ctx.arc(centerX, centerY, radius, startAngle, endAngle);
+    ctx.strokeStyle = canRingDrag?"red":"rgba(255,0,0,0.5)";
+    ctx.lineWidth = 10;
+    ctx.stroke();
+
+
+    ctx.beginPath();
+    ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
+    ctx.fillStyle = '#00ff00';
+    ctx.fill();
+
+    
+
+    
+
+    ctx.beginPath();
+    ctx.arc(pointEndX, pointEndY, 5, 0, 2 * Math.PI);
+    ctx.fillStyle = 'blue';
+    ctx.fill();
+  };
+
+  function twoPointDistance(p1, p2) {
+    let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
+    return dep;
+  }
+
+  function limitAngle(start,end) {
+    var angle1 = start<0?start+2*Math.PI:start;
+    var angle2 = end<0?end+2*Math.PI:end;
+    if (angle2<angle1){
+      angle2 = angle2+2*Math.PI;
+    }
+
+    var leftAngle = angle2-angle1;
+    if (leftAngle>Math.PI*23/12){
+      return 1;
+    }
+    else if (leftAngle<Math.PI/12){
+      return 2;
+    }
+    return 0;
+  }
+
+  function durationAngle(end,start) {
+    var angle1 = start<0?start+2*Math.PI:start;
+    var angle2 = end<0?end+2*Math.PI:end;
+    if (angle2<angle1){
+      angle2 = angle2+2*Math.PI;
+    }
+
+    return angle2-angle1;
+  }
+
+  const handleTouchMove = (e: any) => {
+    if (!canStartDrag && !canEndDrag && !canRingDrag){
+      return;
+    }
+    const ctx = currentContext;//canvasRef.current.getContext('2d');
+    
+    const { x, y } = e.touches[0];
+
+    const centerX = canvasWidth / 2;
+    const centerY = canvasHeight / 2;
+    const radius = Math.min(centerX, centerY) - 10;
+
+    let angle = Math.atan2(y-canvasWidth/2.0, x-canvasWidth/2.0)
+
+    if (canStartDrag){
+      if (Math.abs(durationAngle(endAngle,angle)-lastDuration)>Math.PI){
+        debugger
+        //禁止跨越
+        return;
+      }
+      console.log(durationAngle(endAngle,angle)+'    '+lastDuration)
+
+      var result = limitAngle(angle,endAngle);
+      switch (result){
+        case 0:
+          startAngle = angle;
+          break;
+        case 1:
+          debugger
+          startAngle = endAngle-23*Math.PI/12;
+          break;
+        case 2:
+          debugger
+          startAngle = endAngle-Math.PI/12;
+          break;
+      }
+      
+    }
+
+    if (canEndDrag){
+      if (Math.abs(durationAngle(angle,startAngle)-lastDuration)>Math.PI){
+        //禁止跨越
+        return;
+      }
+
+      var result = limitAngle(startAngle,angle);
+      switch (result){
+        case 0:
+          endAngle = angle;
+          break;
+        case 1:
+          endAngle = startAngle+23*Math.PI/12;
+          break;
+        case 2:
+          endAngle = startAngle+Math.PI/12;
+          break;
+      }
+      
+    }
+
+    // console.log(`startAngle:${startAngle}  endAngle:${endAngle}`)
+
+    if (canRingDrag){
+      // console.log(`lastAngle:${lastAngle}  angle:${angle}`)
+      let delta = angle - lastAngle;
+      startAngle += delta;
+      endAngle += delta;
+      lastAngle = angle;
+    }
+
+    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
+      
+
+    ctx.beginPath();
+    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
+    ctx.strokeStyle = "rgba(0,0,0,0.5)";
+    ctx.lineWidth = 10;
+    ctx.stroke();
+
+    ctx.beginPath();
+    ctx.arc(centerX, centerY, radius, startAngle, endAngle);
+    ctx.strokeStyle = canRingDrag?"red":"rgba(255,0,0,0.5)";
+    ctx.lineWidth = 10;
+    ctx.stroke();
+
+    const pointX = centerX + Math.cos(startAngle) * radius;
+    const pointY = centerY + Math.sin(startAngle) * radius;
+
+    ctx.beginPath();
+    ctx.arc(pointX, pointY, 5, 0, 2 * Math.PI);
+    ctx.fillStyle = '#00ff00';
+    ctx.fill();
+
+
+
+    // 绘制蓝色终点圆点
+    const pointX2 = centerX + Math.cos(endAngle) * radius;
+    const pointY2 = centerY + Math.sin(endAngle) * radius;
+
+    ctx.beginPath();
+    ctx.arc(pointX2, pointY2, 5, 0, 2 * Math.PI);
+    ctx.fillStyle = 'blue';
+    ctx.fill();
+
+    lastDuration = durationAngle(endAngle,startAngle);
+  };
+
+  const handleClick = (e) => {
+
+    const scaleX = 1//dpr//canvasRect.width / canvasRect.width;
+    const scaleY = 1//dpr//canvasRect.height / canvasRect.height;
+    const canvasX = (e.touches[0].x - 0) * scaleX;
+    const canvasY = (e.touches[0].y - 0) * scaleY;
+    console.log(`x:${canvasX}  y:${canvasY}`)
+
+    // const ctx = canvasRef.current.getContext('2d');
+
+    // 判断点击位置是否在圆点范围内
+    const centerX = canvasWidth / 2;
+    const centerY = canvasWidth / 2;
+    const radius = Math.min(centerX, centerY) - 10;
+
+
+    const pointX = centerX + Math.cos(startAngle) * radius;
+    const pointY = centerY + Math.sin(startAngle) * radius;
+    const distance = Math.sqrt(Math.pow(canvasX - pointX, 2) + Math.pow(canvasY - pointY, 2));
+
+    if (distance <= 8) {
+      canStartDrag = true;
+    } else {
+      canStartDrag = false;
+    }
+
+    const pointX2 = centerX + Math.cos(endAngle) * radius;
+    const pointY2 = centerY + Math.sin(endAngle) * radius;
+    const distance2 = Math.sqrt(Math.pow(canvasX - pointX2, 2) + Math.pow(canvasY - pointY2, 2));
+
+    if (distance2 <= 8) {
+      canEndDrag = true;
+    } else {
+      canEndDrag = false;
+    }
+
+    if (canStartDrag || canEndDrag){
+      canRingDrag = false;
+      return;
+    }
+
+    const distance3 = twoPointDistance({x:canvasX,y:canvasY},{x:centerX,y:centerY});
+    let angle = Math.atan2(canvasY-canvasWidth/2.0, canvasX-canvasWidth/2.0)
+    if (distance3>80&& distance3<105 && startAngle<angle && angle<endAngle){
+      canRingDrag = true;
+      console.log("canRingDrag")
+    }
+    console.log(distance3);
+    lastAngle = angle;
+  };
+
+  const handleTouchEnd = (e) =>{
+    canStartDrag = false;
+    canEndDrag = false;
+    canRingDrag = false;
+    console.log('end')
+    handleTouchMove(e)
+  }
+
+  return <View style={{ width: '100%', height: 600, backgroundColor: 'white' }}>
+    <Canvas canvasId={canvasId} id={canvasId} className={canvasId} type="2d"
+      style={{ width: 300, height: 300, zIndex: 0, backgroundColor: 'yellow' }}
+      onTouchMove={handleTouchMove}
+      onTouchEnd={handleTouchEnd}
+      onTouchStart={handleClick}
+      ref={canvasRef} />
+  </View>
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff