微信小步调 实现拼图功能

打印 上一主题 下一主题

主题 1685|帖子 1685|积分 5055

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
效果示例


     微信小步调 碎片拼图
  
功能描述

在微信小步调中,实现一个简单的拼图小游戏。用户需要将四张碎片图片拖动到目标图片的精确位置,详细功能如下:
拖动功能:
用户可以通过手指拖动碎片图片,自由移动到目标图片的任意位置。
位置匹配:
如果碎片被拖动到精确的位置(即与目标图片的预定区域完全重叠或匹配),碎片会主动吸附到目标图片的指定位置,并表现为已完成。
如果碎片被拖动到错误的位置(未能与目标区域匹配),碎片会主动返回到初始位置。
完成检测:
当全部碎片都被精确放置后,触发完成拼图的效果(如表现完整图片、播放动画或提示乐成信息)。
代码示例



  • html
  1. <!--pages/cssCase/puzzle1/index.wxml-->
  2. <view class="container">
  3.   <!-- 上方的拼图框 -->
  4.   <view class="puzzle-box">
  5.     <view class="puzzle-cell" wx:for="{{puzzleCells}}" wx:key="id" id="{{item.id}}" data-id="{{item.id}}">
  6.       <image src="{{item.image}}" class="target-image"></image>
  7.     </view>
  8.   </view>
  9.   <!-- 下方的碎片 --> <!-- 添加 data-index 以传递碎片的索引 -->
  10.   <view class="pieces">
  11.     <view class="piece" wx:for="{{pieces}}" wx:key="id"
  12.       id="{{item.id}}"
  13.       style="left: {{item.left}}px; top: {{item.top}}px;"
  14.       data-id="{{item.id}}"
  15.       data-index="{{index}}"  
  16.       bindtouchstart="onTouchStart"
  17.       bindtouchmove="onTouchMove"
  18.       bindtouchend="onTouchEnd"
  19.       wx:if="{{!item.hidden}}"> <!-- 只有当 hidden 为 false 时才显示碎片 -->
  20.       <image src="{{item.image}}"></image>
  21.     </view>
  22.   </view>
  23. </view>
复制代码


  • css
  1. /* pages/cssCase/puzzle1/index.wxss */
  2. .container {
  3.   display: flex;
  4.   flex-direction: column;
  5.   align-items: center;
  6.   justify-content: center;
  7.   height: 100%;
  8. }
  9. .puzzle-box {
  10.   margin: 20rpx;
  11.   border: 1px solid #ccc;
  12.   display: flex;
  13.   align-items: center;
  14.   justify-content: center;
  15.   flex-wrap: wrap;
  16.   padding: 20rpx;
  17.   box-sizing: border-box;
  18. }
  19. .puzzle-cell {
  20.   width: 300rpx;
  21.   height: 300rpx;
  22.   border: 1rpx solid #ccc;
  23.   position: relative;
  24. }
  25. .target-image {
  26.   width: 300rpx;
  27.   height: 300rpx;
  28. }
  29. .pieces {
  30.   display: flex;
  31.   justify-content: space-between;
  32.   width: 100%;
  33.   padding: 0 10rpx;
  34. }
  35. .piece {
  36.   width: 150rpx;
  37.   height: 150rpx;
  38.   position: absolute;
  39. }
  40. .piece image {
  41.   width: 100%;
  42.   height: 100%;
  43. }
复制代码


  • js
  1. // pages/cssCase/puzzle1/index.js
  2. Page({
  3.   data: {
  4.     puzzleCells: [
  5.       { id: 'cell-1', image: '', correctPieceId: 'piece-1' },
  6.       { id: 'cell-2', image: '', correctPieceId: 'piece-2' },
  7.       { id: 'cell-3', image: '', correctPieceId: 'piece-3' },
  8.       { id: 'cell-4', image: '', correctPieceId: 'piece-4' },
  9.     ],
  10.     pieces: [
  11.       { id: 'piece-1', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce1.jpeg', left: 10, top: 380, originalLeft: 10, originalTop: 380, hidden: false },
  12.       { id: 'piece-2', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce2.jpeg', left: 120, top: 380, originalLeft: 120, originalTop: 380, hidden: false },
  13.       { id: 'piece-3', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce3.jpeg', left: 210, top: 380, originalLeft: 210, originalTop: 380, hidden: false },
  14.       { id: 'piece-4', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce4.jpeg', left: 300, top: 380, originalLeft: 300, originalTop: 380, hidden: false },
  15.     ],
  16.     draggingPiece: null,
  17.     draggingPieceIndex: null, // 用于记录当前拖拽的碎片在 pieces 中的索引
  18.   },
  19.   onTouchStart(e) {
  20.     const { id, index } = e.currentTarget.dataset;
  21.     this.setData({
  22.       draggingPiece: id,
  23.       draggingPieceIndex: index,
  24.     });
  25.   },
  26.   onTouchMove(e) {
  27.     const { pageX, pageY } = e.touches[0];
  28.     const updatedPieces = this.data.pieces.map((piece, index) => {
  29.       if (index === this.data.draggingPieceIndex) {
  30.         return { ...piece, left: pageX - 75, top: pageY - 75 }; // 让碎片跟随手指移动
  31.       }
  32.       return piece;
  33.     });
  34.     this.setData({ pieces: updatedPieces });
  35.   },
  36.   onTouchEnd(e) {
  37.     const { draggingPiece, draggingPieceIndex } = this.data;
  38.     if (!draggingPiece) return;
  39.     const query = wx.createSelectorQuery();
  40.     this.data.puzzleCells.forEach((cell) => {
  41.       query.select(`#${cell.id}`).boundingClientRect();
  42.     });
  43.     query.select(`#${draggingPiece}`).boundingClientRect();
  44.     query.exec((res) => {
  45.       const cellRects = res.slice(0, this.data.puzzleCells.length);
  46.       const pieceRect = res[res.length - 1];
  47.       let placed = false;
  48.       cellRects.forEach((cellRect, index) => {
  49.         const cell = this.data.puzzleCells[index];
  50.         if (cell.correctPieceId === draggingPiece && this.checkOverlap(cellRect, pieceRect)) {
  51.           placed = true;
  52.           this.updatePuzzleCellImage(index, this.data.pieces[draggingPieceIndex].image);
  53.           this.hidePiece(draggingPieceIndex);
  54.           this.updatePiecePosition(draggingPieceIndex, cellRect.left, cellRect.top);
  55.         }
  56.       });
  57.       if (!placed) {
  58.         this.resetPiecePosition(draggingPieceIndex);
  59.       }
  60.       this.setData({ draggingPiece: null });
  61.       // 检查是否完成拼图
  62.       this.checkCompletion();
  63.     });
  64.   },
  65.   checkOverlap(box1, box2) {
  66.     return (
  67.       box1.left < box2.left + box2.width &&
  68.       box1.left + box1.width > box2.left &&
  69.       box1.top < box2.top + box2.height &&
  70.       box1.top + box1.height > box2.top
  71.     );
  72.   },
  73.   updatePuzzleCellImage(cellIndex, image) {
  74.     const updatedCells = [...this.data.puzzleCells];
  75.     updatedCells[cellIndex].image = image;
  76.     this.setData({ puzzleCells: updatedCells });
  77.   },
  78.   hidePiece(pieceIndex) {
  79.     const updatedPieces = this.data.pieces.map((piece, index) => {
  80.       if (index === pieceIndex) {
  81.         return { ...piece, hidden: true }; // 设置碎片为隐藏
  82.       }
  83.       return piece;
  84.     });
  85.     this.setData({ pieces: updatedPieces });
  86.   },
  87.   updatePiecePosition(pieceIndex, left, top) {
  88.     const updatedPieces = this.data.pieces.map((piece, index) => {
  89.       if (index === pieceIndex) {
  90.         return { ...piece, left, top };
  91.       }
  92.       return piece;
  93.     });
  94.     this.setData({ pieces: updatedPieces });
  95.   },
  96.   resetPiecePosition(pieceIndex) {
  97.     const updatedPieces = this.data.pieces.map((piece, index) => {
  98.       if (index === pieceIndex) {
  99.         return { ...piece, left: piece.originalLeft, top: piece.originalTop };
  100.       }
  101.       return piece;
  102.     });
  103.     this.setData({ pieces: updatedPieces });
  104.   },
  105.   // 检查拼图是否完成
  106.   checkCompletion() {
  107.     const allPiecesPlaced = this.data.pieces.every((piece) => piece.hidden);
  108.     if (allPiecesPlaced) {
  109.       wx.showToast({
  110.         title: '拼图完成!',
  111.         icon: 'success',
  112.         duration: 2000,
  113.       });
  114.     }
  115.   },
  116. });
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万万哇

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表