|
|
@@ -1,278 +1,12 @@
|
|
|
-import Taro from '@tarojs/taro';
|
|
|
import { Canvas, View,Text } from '@tarojs/components';
|
|
|
-import { useEffect, useRef } from 'react';
|
|
|
-import Timeline from '@/components/view/Timeline';
|
|
|
-import RecordItem from '@/features/common/RecordItem';
|
|
|
-
|
|
|
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.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();
|
|
|
- };
|
|
|
-
|
|
|
- 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) => {
|
|
|
- const ctx = currentContext;//canvasRef.current.getContext('2d');
|
|
|
- if (!canStartDrag && !canEndDrag && !canRingDrag) {
|
|
|
- drawCanvas(ctx);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const { x, y } = e.touches[0];
|
|
|
-
|
|
|
- let angle = Math.atan2(y - canvasWidth / 2.0, x - canvasWidth / 2.0)
|
|
|
-
|
|
|
- if (canStartDrag) {
|
|
|
- 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) {
|
|
|
- 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) {
|
|
|
- let delta = angle - lastAngle;
|
|
|
- startAngle += delta;
|
|
|
- endAngle += delta;
|
|
|
- lastAngle = angle;
|
|
|
- }
|
|
|
-
|
|
|
- drawCanvas(ctx);
|
|
|
-
|
|
|
- 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;
|
|
|
-
|
|
|
- // 判断点击位置是否在圆点范围内
|
|
|
- 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;
|
|
|
- }
|
|
|
- lastAngle = angle;
|
|
|
-
|
|
|
- drawCanvas(currentContext);
|
|
|
- };
|
|
|
-
|
|
|
- const handleTouchEnd = (e) => {
|
|
|
- canStartDrag = false;
|
|
|
- canEndDrag = false;
|
|
|
- canRingDrag = false;
|
|
|
- handleTouchMove(e)
|
|
|
- }
|
|
|
-
|
|
|
- const timelineItems = [
|
|
|
- {
|
|
|
- status: 'padding',
|
|
|
- content: 'Item 1',
|
|
|
- time: '10:00 AM',
|
|
|
- },
|
|
|
- {
|
|
|
- status: 'done',
|
|
|
- content: 'Item 2',
|
|
|
- time: '11:00 AM',
|
|
|
- },
|
|
|
- {
|
|
|
- status: 'un_done',
|
|
|
- content: 'Item 3',
|
|
|
- time: '12:00 PM',
|
|
|
- },
|
|
|
- ];
|
|
|
-
|
|
|
- return <View style={{ width: '100%', height: 600, backgroundColor: 'white',display:'flex',flexDirection:'column' }}>
|
|
|
- <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} />
|
|
|
- <Timeline items={timelineItems} />
|
|
|
- <RecordItem>
|
|
|
- <Text>sldifjgsdgpsg</Text>
|
|
|
- </RecordItem>
|
|
|
-
|
|
|
+ return <View style={{width:'100vw',height:'100vh',backgroundColor:'#000'}}>
|
|
|
+ <View style={{
|
|
|
+ width:200,
|
|
|
+ height:200,
|
|
|
+ marginTop:200,
|
|
|
+ borderRadius:32,
|
|
|
+ backgroundColor:'#1c1c1c'
|
|
|
+ }}></View>
|
|
|
</View>
|
|
|
}
|