需求
这次的需求有点难描述,设计图的一部分长这样:
最终实现效果呈这样:
天知道这圆环的纹路还要不要实现,暂时是无能为力了,主要是不知道怎么问AI效果都不对,以后解决了再更新。
需求分析
首先是这圆环了跟这个可移动的小圆了,问了百度的AI,没用Canvas,纯手搓的效果相当差,在屏幕中到处跑,根本束缚不住。
当时在搜相关有用的代码时发现别人用的Canvas代码,算是帮了大忙: 大佬代码,因为比较新,对于我接下来使用谷歌浏览器的Sider使用的chatgpt3.5版AI时代码比较旧,有些代码已经被微信小程序弃用了,参考一下大佬的才算是转换过来。
1、圆环与可控制移动的点
问(PS.问了N次):微信小程序ui实现绕固定原点与半径的可控制移动的点,请提供代码
答:以下是一个示例代码,它可以在微信小程序中实现一个点围绕固定原点(圆心)按给定半径进行可控制的移动。用户可以通过滑动手指在屏幕上改变点的位置。
- WXML 文件
在你的 WXML 文件中添加一个 控件,并设置相应的样式。
<view class="container">
<canvas canvas-id="circleCanvas" style="width: 300px; height: 300px;" bindtouchmove="onTouchMove" bindtouchend="onTouchEnd"></canvas>
</view>
- JS 文件
在 JavaScript 文件中,编写逻辑以控制点的绘制和更新。
Page({
data: {
centerX: 150, // 圆心的X坐标
centerY: 150, // 圆心的Y坐标
radius: 100, // 圆的半径
angle: 0 // 当前角度
},
onReady: function () {
this.drawCircle(); // 页面加载完成后绘制圆和点
},
drawCircle: function () {
const ctx = wx.createCanvasContext('circleCanvas', this);
const { centerX, centerY, radius } = this.data;
// 清空画布
ctx.clearRect(0, 0, 300, 300);
// 绘制圆
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
ctx.setStrokeStyle('#ccc'); // 设置圆圈颜色
ctx.setLineWidth(2); // 设置线宽
ctx.stroke(); // 绘制圆圈
// 绘制点
this.drawPoint(ctx); // 绘制圆周上的点
ctx.draw(); // 绘制到画布
},
drawPoint: function (ctx) {
const { centerX, centerY, radius, angle } = this.data;
// 计算点在圆周上的位置
const pointX = centerX + radius * Math.cos(angle); // 点的X坐标
const pointY = centerY + radius * Math.sin(angle); // 点的Y坐标
// 绘制点
ctx.beginPath();
ctx.arc(pointX, pointY, 10, 0, 2 * Math.PI); // 点的半径为10
ctx.setFillStyle('#000'); // 设置点的颜色
ctx.fill(); // 填充点
},
onTouchMove: function (e) {
const touch = e.touches[0]; // 获取手指触控的位置
const { centerX, centerY } = this.data;
// 计算当前触摸点与圆心的距离
const dx = touch.x - centerX; // 使用 touch.x 而不是 clientX
const dy = touch.y - centerY; // 使用 touch.y 而不是 clientY
const distance = Math.sqrt(dx * dx + dy * dy);
// 计算当前角度
let angle = Math.atan2(dy, dx);
if (distance > this.data.radius) {
// 如果超过半径,则按半径限制
angle = Math.atan2(dy / distance * this.data.radius, dx / distance * this.data.radius);
}
this.setData({ angle }); // 更新当前角度
this.drawCircle(); // 重新绘制
},
onTouchEnd: function () {
// 可以根据需要在触摸结束时添加逻辑
}
});
- CSS 文件
在 CSS 文件中添加一些基本的样式以美化界面。
.container {
display: flex;
align-items: center;
justify-content: center;
height: 100vh; /* 充满屏幕高度 */
}
代码说明
数据初始化: 我们定义了圆心的位置(centerX 和 centerY)、圆的半径(radius)以及当前的角度(angle)。
绘制圆和点:
在 drawCircle() 方法中,首先清空画布,然后描绘一个灰色的圆和当前点的黑色圆。
drawPoint(ctx) 函数用于计算点的位置并将其绘制到圆周上。
手指移动控制:
onTouchMove() 方法获取当前触摸点的坐标,并计算这个点到圆心的距离和角度。
使用 Math.atan2(dy, dx) 计算当前点的角度,并根据实际情况限制该点在指定半径内移动。
样式设置: 简单的 CSS 使得界面居中。
2、渐变色的圆
问:点的颜色是从上往下渲染而成
答:如果你希望点的颜色在整个圆形上实现从上往下的渐变效果,可以使用 createRadialGradient 创建一个圈的径向渐变效果,但为更符合“从上往下渲染”的效果,我们可以考虑使用 createLinearGradient 方法来创建一个线性渐变,并将其应用于绘制的圆形。
实现从上往下的线性渐变
以下是一个示例代码,展示如何实现这个效果:
drawPoint: function (ctx) {
const { centerX, centerY, radius, angle } = this.data;
// 计算点在圆周上的位置
const pointX = centerX + radius * Math.cos(angle); // 点的X坐标
const pointY = centerY + radius * Math.sin(angle); // 点的Y坐标
// 创建从上到下的线性渐变
const gradient = ctx.createLinearGradient(pointX, pointY - 10, pointX, pointY + 10); // 从点上方到下方的渐变
gradient.addColorStop(0, 'red'); // 上部为红色
gradient.addColorStop(1, 'blue'); // 下部为蓝色
// 绘制点
ctx.beginPath();
ctx.arc(pointX, pointY, 10, 0, 2 * Math.PI); // 点的半径为10
ctx.setFillStyle(gradient); // 使用创建的渐变色
ctx.fill(); // 填充点
}
解释代码
创建线性渐变:
ctx.createLinearGradient(pointX, pointY - 10, pointX, pointY + 10):创建一个从 pointY - 10(点的上方)到 pointY + 10(点的下方)的线性渐变。
addColorStop(0,