微信小程序手串DIY功能开发实录:飞入动画 + 环形排布 + 拖拽换序 + 旋转查看 + 保存设计

最近在做一个文玩类小程序,核心需求是让用户能自由在手机上搭配手串。下面直接从功能维度梳理一下,这个项目到底完成了哪些事,并附上关键代码片段。

功能全景:用户能做哪些操作?

整个功能围绕"串珠子"这个核心行为展开,覆盖了从选材到保存的全流程。

1️⃣ 珠子添加(飞入动画)

用户点击底部珠子库中的任意珠子,珠子会从屏幕下方飞入手串的空缺位置。

飞入过程约0.4秒,带有透明度渐变

落点精确对应手串上的预留角度

动画结束后珠子自动归位到手串序列中

javascript 复制代码
startBeadFlightAnimation(bead, callback) {
  const startX = this.data.windowWidth / 2;
  const startY = 800 / 750 * this.data.windowWidth;
  const targetPos = this.calculateTargetPosition(bead.targetAngle);

  this.setData({
    flyingBead: { show: true, x: startX, y: startY, opacity: 0 }
  });

  setTimeout(() => {
    this.setData({
      flyingBead: { show: true, x: targetPos.x, y: targetPos.y, opacity: 0.8 }
    });
  }, 100);

  setTimeout(() => {
    this.setData({ flyingBead: { show: false } });
    callback && callback();
  }, 500);
}

2️⃣ 环形自动排布

所有珠子按照极坐标分布在圆形手串上,无需手动对齐。

根据珠子数量自动计算间距

若珠子总体积超过手串周长,自动等比缩小每颗珠子

每颗珠子记录独立的角度坐标,旋转时不乱位

核心代码(动态缩放与角度分配):

javascript 复制代码
handleMultipleBeads(n, handchain, newBead) {
  let allLength = 0;
  for (let i = 0; i < n; i++) {
    allLength += handchain[i].radius * 2 * 10;
  }
  allLength += newBead.radius * 2 * 10;

  const perimeter = 510 * Math.PI;
  let scale = perimeter / allLength;
  if (scale > 1) scale = 1;

  let spacing = (360 - (allLength * scale / perimeter * 360)) / (n + 1);
  this.setData({ scale });

  // 为每个珠子分配新的targetAngle
  let accumulated = 0;
  for (let i = 0; i < n; i++) {
    handchain[i].targetAngle = 300 - (n - i) * spacing - accumulated;
    accumulated += handchain[i].radius * scale * 10 / (perimeter / 360);
  }
}

3️⃣ 单指旋转查看

用户用手指在手串区域滑动,整串手串会跟随手指方向旋转。

360°无死角查看

旋转角度实时跟随手指位移

旋转过程中所有珠子保持相对位置不变

核心代码(旋转角度增量计算):

javascript 复制代码
onTouchMove(e) {
  const touch = e.touches[0];
  const currentAngle = this.getAngle(touch.clientX, touch.clientY);
  let angleDiff = currentAngle - this.currentAngle;

  if (angleDiff > 180) angleDiff -= 360;
  if (angleDiff < -180) angleDiff += 360;

  const newHandchain = this.data.handchain.map(bead => ({
    ...bead,
    targetAngle: bead.targetAngle + angleDiff
  }));

  this.setData({
    handchain: newHandchain,
    totalAngle: this.data.totalAngle + angleDiff
  });
  this.currentAngle = currentAngle;
}

4️⃣ 拖拽互换位置

长按某颗珠子,可以将其拖拽到另一个位置,其他珠子会自动让位。

系统自动判断顺时针还是逆时针交换更近

被拖拽的珠子半透明跟随手指

其余珠子平滑移动到新位置,无闪烁

核心代码(最短路径交换逻辑):

javascript 复制代码
// 判断顺时针距离 vs 逆时针距离
const clockwiseDist = (targetArea - originalArea + n) % n;
const counterClockwiseDist = (originalArea - targetArea + n) % n;

if (clockwiseDist <= counterClockwiseDist) {
  // 顺时针逐个交换相邻珠子角度
  for (let i = originalArea; i !== targetArea; i = (i + 1) % n) {
    swapAdjacentAngles(sortedHandchain, i, (i + 1) % n);
  }
} else {
  // 逆时针逐个交换
  for (let i = originalArea; i !== targetArea; i = (i - 1 + n) % n) {
    swapAdjacentAngles(sortedHandchain, i, (i - 1 + n) % n);
  }
}

5️⃣ 拖远删除

将珠子拖到手串圆圈之外(超过设定阈值),松手即可删除。

删除后剩余珠子自动重新排列,填补空缺

有明确的视觉边界提示

核心代码(距离判断与删除):

javascript 复制代码
touchBeadEnd(e) {
  const distance = Math.sqrt(
    Math.pow(this.data.draggingBead.x - this.data.handchainInfo.centerX, 2) +
    Math.pow(this.data.draggingBead.y - this.data.handchainInfo.centerY, 2)
  );
  const maxDistance = 350 / 750 * this.data.windowWidth;

  if (distance > maxDistance) {
    this.removeBead(e); // 调用删除方法
  } else {
    // 复位珠子可见性
  }
}

6️⃣ 状态持久化

用户搭配好的手串可以保存,下次进入自动恢复。

一键保存到本地缓存

支持加载上一次设计

支持一键重置清空

核心代码(存储与读取):

javascript 复制代码
saveDesign() {
  const design = { handchain: this.data.handchain, saveTime: new Date().toLocaleString() };
  wx.setStorageSync('handchainDesign', design);
  wx.showToast({ title: '设计已保存', icon: 'success' });
}

loadSavedDesign() {
  const saved = wx.getStorageSync('handchainDesign');
  if (saved && saved.handchain) {
    this.setData({ handchain: saved.handchain });
  }
}

交互闭环:从选择到完成

整个功能形成了一个完整的用户操作链路:

浏览珠子库 → 点击添加(飞入动画) → 旋转查看 → 拖拽调整顺序 → 拖远删除不满意的 → 保存设计

每一步操作都有对应的视觉反馈,用户无需学习成本,凭直觉即可完成一套手串的DIY。

技术要点简述

布局算法:极坐标 + 动态缩放,解决环形排列问题

动画系统:CSS transition + setTimeout 控制飞入和交换动画

拖拽逻辑:触摸点转角度 → 判断所在区间 → 最短路径交换

旋转处理:触摸角度差累加到所有珠子的目标角度

性能优化:减少setData频率,使用局部更新

总结

这套手串DIY功能从零开始搭建,完成了从交互设计到动画实现的全链路开发。核心价值在于:把一个传统的"选配"流程,变成了一个直观好玩的"动手"体验。

如果你也在做类似的商品自定义搭配功能,希望这份功能清单和代码片段能给你一些参考。欢迎评论区交流 👋

相关推荐
admin and root3 天前
「移动安全」安卓APP 反编译&frida脱壳技巧分享
android·开发语言·python·web安全·微信小程序·移动安全·攻防演练
m0_462803884 天前
【无标题】
微信小程序
码农学院5 天前
微信小程序云开发实战:扫码点餐系统的高并发订单处理与外卖接单架构
微信小程序·架构·notepad++
这是个栗子6 天前
uni-app 微信小程序开发:常用函数总结(一)
微信小程序·小程序·uni-app·getcurrentpages
爱勇宝6 天前
上线 20 多天后,我才发现小程序的图片上传一直不可用
微信小程序·智能小程序
万亿少女的梦1688 天前
基于微信小程序、Spring Boot与Vue3的智慧养老管理系统设计与实现
spring boot·redis·微信小程序·mybatis·vue3
alxraves9 天前
零代码AI助手:用大模型自动生成微信小程序界面与逻辑
人工智能·微信小程序·notepad++
秃头披风侠_郑9 天前
【uniapp】一文让你学会微信小程序+APP+H5全平台实战指南
前端·微信小程序·uni-app
爱勇宝10 天前
一个家庭成长小程序的 MVP 复盘:看到用户在用我很欣慰
微信小程序·产品·设计
这是个栗子10 天前
uni-app微信小程序开发:高频核心 API(三)
微信小程序·小程序·uni-app