微信小程序 实现拼图功能

embedded/2025/1/15 23:20:58/

微信小程序 实现拼图

  • 效果示例
  • 功能描述
  • 代码示例

效果示例

微信小程序 碎片拼图

功能描述

微信小程序中,实现一个简单的拼图小游戏。用户需要将四张碎片图片拖动到目标图片的正确位置,具体功能如下:

拖动功能:
用户可以通过手指拖动碎片图片,自由移动到目标图片的任意位置。

位置匹配:

如果碎片被拖动到正确的位置(即与目标图片的预定区域完全重叠或匹配),碎片会自动吸附到目标图片的指定位置,并显示为已完成。
如果碎片被拖动到错误的位置(未能与目标区域匹配),碎片会自动返回到初始位置。

完成检测:
当所有碎片都被正确放置后,触发完成拼图的效果(如显示完整图片、播放动画或提示成功信息)。

代码示例

  • html
<!--pages/cssCase/puzzle1/index.wxml-->
<view class="container"><!-- 上方的拼图框 --><view class="puzzle-box"><view class="puzzle-cell" wx:for="{{puzzleCells}}" wx:key="id" id="{{item.id}}" data-id="{{item.id}}"><image src="{{item.image}}" class="target-image"></image></view></view><!-- 下方的碎片 --> <!-- 添加 data-index 以传递碎片的索引 --><view class="pieces"><view class="piece" wx:for="{{pieces}}" wx:key="id" id="{{item.id}}" style="left: {{item.left}}px; top: {{item.top}}px;" data-id="{{item.id}}" data-index="{{index}}"  bindtouchstart="onTouchStart" bindtouchmove="onTouchMove" bindtouchend="onTouchEnd"wx:if="{{!item.hidden}}"> <!-- 只有当 hidden 为 false 时才显示碎片 --><image src="{{item.image}}"></image></view></view>
</view>
  • css
/* pages/cssCase/puzzle1/index.wxss */
.container {display: flex;flex-direction: column;align-items: center;justify-content: center;height: 100%;
}.puzzle-box {margin: 20rpx;border: 1px solid #ccc;display: flex;align-items: center;justify-content: center;flex-wrap: wrap;padding: 20rpx;box-sizing: border-box;
}.puzzle-cell {width: 300rpx;height: 300rpx;border: 1rpx solid #ccc;position: relative;
}
.target-image {width: 300rpx;height: 300rpx;
}.pieces {display: flex;justify-content: space-between;width: 100%;padding: 0 10rpx;
}.piece {width: 150rpx;height: 150rpx;position: absolute;
}.piece image {width: 100%;height: 100%;
}
  • js
// pages/cssCase/puzzle1/index.js
Page({data: {puzzleCells: [{ id: 'cell-1', image: '', correctPieceId: 'piece-1' },{ id: 'cell-2', image: '', correctPieceId: 'piece-2' },{ id: 'cell-3', image: '', correctPieceId: 'piece-3' },{ id: 'cell-4', image: '', correctPieceId: 'piece-4' },],pieces: [{ id: 'piece-1', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce1.jpeg', left: 10, top: 380, originalLeft: 10, originalTop: 380, hidden: false },{ id: 'piece-2', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce2.jpeg', left: 120, top: 380, originalLeft: 120, originalTop: 380, hidden: false },{ id: 'piece-3', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce3.jpeg', left: 210, top: 380, originalLeft: 210, originalTop: 380, hidden: false },{ id: 'piece-4', image: 'https://static.sprucesmart.com/activity/shandong/jigsawPuzzle20250109/ce4.jpeg', left: 300, top: 380, originalLeft: 300, originalTop: 380, hidden: false },],draggingPiece: null,draggingPieceIndex: null, // 用于记录当前拖拽的碎片在 pieces 中的索引},onTouchStart(e) {const { id, index } = e.currentTarget.dataset;this.setData({draggingPiece: id,draggingPieceIndex: index,});},onTouchMove(e) {const { pageX, pageY } = e.touches[0];const updatedPieces = this.data.pieces.map((piece, index) => {if (index === this.data.draggingPieceIndex) {return { ...piece, left: pageX - 75, top: pageY - 75 }; // 让碎片跟随手指移动}return piece;});this.setData({ pieces: updatedPieces });},onTouchEnd(e) {const { draggingPiece, draggingPieceIndex } = this.data;if (!draggingPiece) return;const query = wx.createSelectorQuery();this.data.puzzleCells.forEach((cell) => {query.select(`#${cell.id}`).boundingClientRect();});query.select(`#${draggingPiece}`).boundingClientRect();query.exec((res) => {const cellRects = res.slice(0, this.data.puzzleCells.length);const pieceRect = res[res.length - 1];let placed = false;cellRects.forEach((cellRect, index) => {const cell = this.data.puzzleCells[index];if (cell.correctPieceId === draggingPiece && this.checkOverlap(cellRect, pieceRect)) {placed = true;this.updatePuzzleCellImage(index, this.data.pieces[draggingPieceIndex].image);this.hidePiece(draggingPieceIndex);this.updatePiecePosition(draggingPieceIndex, cellRect.left, cellRect.top);}});if (!placed) {this.resetPiecePosition(draggingPieceIndex);}this.setData({ draggingPiece: null });// 检查是否完成拼图this.checkCompletion();});},checkOverlap(box1, box2) {return (box1.left < box2.left + box2.width &&box1.left + box1.width > box2.left &&box1.top < box2.top + box2.height &&box1.top + box1.height > box2.top);},updatePuzzleCellImage(cellIndex, image) {const updatedCells = [...this.data.puzzleCells];updatedCells[cellIndex].image = image;this.setData({ puzzleCells: updatedCells });},hidePiece(pieceIndex) {const updatedPieces = this.data.pieces.map((piece, index) => {if (index === pieceIndex) {return { ...piece, hidden: true }; // 设置碎片为隐藏}return piece;});this.setData({ pieces: updatedPieces });},updatePiecePosition(pieceIndex, left, top) {const updatedPieces = this.data.pieces.map((piece, index) => {if (index === pieceIndex) {return { ...piece, left, top };}return piece;});this.setData({ pieces: updatedPieces });},resetPiecePosition(pieceIndex) {const updatedPieces = this.data.pieces.map((piece, index) => {if (index === pieceIndex) {return { ...piece, left: piece.originalLeft, top: piece.originalTop };}return piece;});this.setData({ pieces: updatedPieces });},// 检查拼图是否完成checkCompletion() {const allPiecesPlaced = this.data.pieces.every((piece) => piece.hidden);if (allPiecesPlaced) {wx.showToast({title: '拼图完成!',icon: 'success',duration: 2000,});}},
});

http://www.ppmy.cn/embedded/154231.html

相关文章

react生命周期方法

一、挂载阶段 constructor&#xff1a;组件的构造函数&#xff0c;初始化state。statiic getDerivedStateFromProps:在组件实例被创建和更新之前调用&#xff0c;返回一个对象来更新state。render:渲染组件的UI。componentDidMount组件挂载完成后调用&#xff0c;通常用于发起…

华为2024嵌入式研发面试题

01 你认为最好的排序算法是什么&#xff1f; 在实际的编程中&#xff0c;最好的排序算法要根据实际需求和数据规模来选择&#xff0c;因为每种排序算法都有其优势和劣势。以下是一些常见排序算法及其优缺点&#xff1a; 冒泡排序 冒泡排序是一种简单直观的排序算法&#xff0…

c#-Halcon入门教程——标定

Halcon代码 read_image (NinePointCalibration, D:/Desktop/halcon/ca74d-main/九点标定/NinePointCalibration.gif)rgb1_to_gray (NinePointCalibration, GrayImage)get_image_size (GrayImage, Width, Height) dev_display (GrayImage)* 获取当前显示的窗口句柄 dev_get_win…

Linux IPC:管道与FIFO汇总整理

管道&#xff08;Pipes&#xff09;和先进先出&#xff08;FIFOs&#xff0c;也称为命名管道&#xff09;都是Linux中用于进程间通信&#xff08;IPC&#xff09;的机制。它们允许数据从一个进程流向另一个进程&#xff0c;类似于命令行中的管道操作符 |。下面详细介绍这两种机…

神经网络

“损失函数 王木头学科学-哔哩哔哩_bilibili 一、transformer和注意力机制的本质&#xff0c;以及编码和解码的结构及其与注意力机制的关系&#xff0c;帮助理解transformer的优势和应用场景。 00:01 - 介绍transformer是人工智能主流技术&#xff0c;大语言模型GBT是在其基础…

宁德时代C++后端开发面试题及参考答案

请阐述面向对象的三大特性。 面向对象编程有三大特性,分别是封装、继承和多态。 封装是指将数据和操作数据的方法绑定在一起,对数据的访问和操作进行限制。这样做的好处是可以隐藏对象的内部细节,只暴露必要的接口给外部。例如,我们可以把一个汽车类的内部引擎状态、速度等…

macOS 如何终止端口占用的进程 ?

您是否遇到过这样的情况&#xff1a;您试图在 Mac 上启动服务器或服务&#xff0c;却被告知端口已被占用&#xff1f;当您试图使用的端口被另一个进程占用时&#xff0c;就会出现此问题。在本教程中&#xff0c;我们将指导您完成在 macOS 上识别和终止这些进程的步骤&#xff0…

C#学习笔记 --- 简单应用

1.operator 运算符重载&#xff1a;使自定义类可以当做操作数一样进行使用。规则自己定。 2.partial 分部类&#xff1a; 同名方法写在不同位置&#xff0c;可以当成一个类使用。 3.索引器&#xff1a;使自定义类可以像数组一样通过索引值 访问到对应的数据。 4.params 数…