|
|
@@ -1,68 +1,333 @@
|
|
|
import Taro from '@tarojs/taro';
|
|
|
-import { View, Canvas } from '@tarojs/components';
|
|
|
-import { useRef, useState } from 'react';
|
|
|
-
|
|
|
-function MyComponent() {
|
|
|
- const [ringX, setRingX] = useState(150);
|
|
|
- const [ringY, setRingY] = useState(150);
|
|
|
- const [dotX, setDotX] = useState(150);
|
|
|
- const [dotY, setDotY] = useState(50);
|
|
|
- const touchStartRef = useRef({ x: 0, y: 0 });
|
|
|
- const dotRef = useRef<any>(null);
|
|
|
+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,endAngle;
|
|
|
+ var lastAngle;
|
|
|
+
|
|
|
+ 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 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 handleTouchStart = (e) => {
|
|
|
- const { clientX, clientY } = e.touches[0];
|
|
|
- touchStartRef.current = { x: clientX, y: clientY };
|
|
|
+
|
|
|
+ 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();
|
|
|
};
|
|
|
|
|
|
- const handleTouchMove = (e) => {
|
|
|
- const { clientX, clientY } = e.touches[0];
|
|
|
- const deltaX = clientX - touchStartRef.current.x;
|
|
|
- const deltaY = clientY - touchStartRef.current.y;
|
|
|
- const newDotX = dotX + deltaX;
|
|
|
- const newDotY = dotY + deltaY;
|
|
|
- const distance = Math.sqrt((newDotX - ringX) ** 2 + (newDotY - ringY) ** 2);
|
|
|
-
|
|
|
- if (distance <= 50) {
|
|
|
- setDotX(newDotX);
|
|
|
- setDotY(newDotY);
|
|
|
+ function twoPointDistance(p1, p2) {
|
|
|
+ let dep = Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2));
|
|
|
+ return dep;
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleTouchMove = (e: any) => {
|
|
|
+ if (!canStartDrag && !canEndDrag && !canRingDrag){
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- touchStartRef.current = { x: clientX, y: clientY };
|
|
|
- drawRingAndDot();
|
|
|
+ if (canEndDrag){
|
|
|
+ endAngle = angle;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ ctx.beginPath();
|
|
|
+ ctx.arc(pointX2, pointY2, 5, 0, 2 * Math.PI);
|
|
|
+ ctx.fillStyle = 'blue';
|
|
|
+ ctx.fill();
|
|
|
};
|
|
|
|
|
|
- const drawRingAndDot = () => {
|
|
|
- const context = Taro.createCanvasContext('myCanvas', this.$scope);
|
|
|
- context.clearRect(0, 0, 300, 300);
|
|
|
- context.beginPath();
|
|
|
- context.arc(ringX, ringY, 50, 0, 2 * Math.PI);
|
|
|
- context.setStrokeStyle('gray');
|
|
|
- context.setLineWidth(10);
|
|
|
- context.stroke();
|
|
|
- context.closePath();
|
|
|
-
|
|
|
- context.beginPath();
|
|
|
- context.arc(dotX, dotY, 10, 0, 2 * Math.PI);
|
|
|
- context.setFillStyle('red');
|
|
|
- context.fill();
|
|
|
- context.closePath();
|
|
|
-
|
|
|
- context.draw();
|
|
|
+ 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 <= 5) {
|
|
|
+ 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 <= 5) {
|
|
|
+ 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;
|
|
|
};
|
|
|
|
|
|
- return (
|
|
|
- <View>
|
|
|
- <Canvas
|
|
|
- id="myCanvas"
|
|
|
- style={{ width: '300px', height: '300px' }}
|
|
|
- onTouchStart={handleTouchStart}
|
|
|
- onTouchMove={handleTouchMove}
|
|
|
- ref={canvasRef}
|
|
|
- />
|
|
|
- </View>
|
|
|
- );
|
|
|
+ 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>
|
|
|
}
|
|
|
|
|
|
-export default MyComponent;
|
|
|
+// 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;
|