微信小程序 实现拼图功能

微信小程序 实现拼图

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

效果示例

微信小程序 碎片拼图

功能描述

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

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

位置匹配:

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

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

代码示例

  • 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,
      });
    }
  },
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955474.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业级NoSQL数据库Redis

1.浏览器缓存过期机制 1.1 最后修改时间 last-modified 浏览器缓存机制是优化网页加载速度和减少服务器负载的重要手段。以下是关于浏览器缓存过期机制、Last-Modified 和 ETag 的详细讲解: 一、Last-Modified 头部 定义:Last-Modified 表示服务器上资源的最后修改时间。 作…

FPGA车牌识别

基于FPGA的车牌识别主要包含以下几个步骤&#xff1a;图像采集、颜色空间转换、边缘检测、形态学处理&#xff08;腐蚀和膨胀&#xff09;、特征值提取、模板匹配、结果显示。先用matlab对原理进行仿真&#xff0c;后用vivado和modelsim进行设计和仿真。 一、1.图像采集采用ov…

客户案例:致远OA与携程商旅集成方案

一、前言 本项目原型客户公司创建于1992年,主要生产并销售包括糖果系列、巧克力系列、烘焙系列、卤制品系列4大类,200多款产品。公司具有行业领先的生产能力,拥有各类生产线100条,年产能超过10万吨。同时,经过30年的发展,公司积累了完善的销售网络,核心经销商已经超过1200个,超…

怎么修复损坏的U盘?而且不用格式化的方式!

当你插入U盘时&#xff0c;若电脑弹出“需要格式化才能使用”提示&#xff0c;且无法打开或读取其中的数据&#xff0c;说明U盘极有可能已经损坏。除此之外&#xff0c;若电脑在连接U盘后显示以下信息&#xff0c;也可能意味着U盘出现问题&#xff0c;需要修复损坏的U盘&#x…

贪心算法(题1)区间选点

输出 2 #include <iostream> #include<algorithm>using namespace std;const int N 100010 ;int n; struct Range {int l,r;bool operator <(const Range &W)const{return r<W.r;} }range[N];int main() {scanf("%d",&n);for(int i0;i&l…

2.使用Spring BootSpring AI快速构建AI应用程序

Spring AI 是基于 Spring Boot3.x 框架构建&#xff0c;Spring Boot官方提供了非常便捷的工具Spring Initializr帮助开发者快速的搭建Spring Boot应用程序,IDEA也集成了此工具。本文使用的开发工具IDEASpring Boot 3.4Spring AI 1.0.0-SNAPSHOTMaven。 1.创建Spring Boot项目 …

【Linux】Socket编程-TCP构建自己的C++服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; Socket 编程 TCP &#x1f98b; TCP socket API 详解&#x1f98b; 多线程远程命令执行&#x1f98b; 网络版计算器&#xff08;应用层自定义协议与序列化…

森林网络部署,工业4G路由器实现林区组网远程监控

在广袤无垠的林区&#xff0c;每一片树叶的摇曳、每一丝空气的流动&#xff0c;都关乎着生态的平衡与安宁。林区监控正以强大的力量&#xff0c;为这片绿色家园筑起一道坚固的防线。 工业 4G 路由器作为林区监控组网的守护者&#xff0c;凭借着卓越的通讯性能&#xff0c;突破…

数据库管理-第284期 奇怪的sys.user$授权(20250116)

数据库管理284期 20245-01-16 数据库管理-第284期 奇怪的sys.user$授权&#xff08;20250116&#xff09;1 问题2 CDB与PDB3 跨实例3.1 通过scanip访问数据库3.2 通过节点1的VIP访问数据库3.3 通过节点3的VIP访问数据库3.4 在节点3赋权后测试3.5 小结 总结 数据库管理-第284期 …

vue2配置跨域后请求的是本机

这个我来说明一下&#xff0c;因为我们公司的后端设置解决了跨域问题&#xff0c;所以我有很久没有看相关的内容了&#xff0c;然后昨天请求了需要跨域的接口&#xff0c;请求半天一直不对&#xff0c;浏览器显示的是本机地址&#xff0c;我以为是自己配置错了&#xff0c;后面…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中&#xff0c;51 单片机就像一颗独特的星辰&#xff0c;散发着神秘而迷人的光芒。对于无数电子爱好者而言&#xff0c;点亮 51 单片机上的第一颗 LED 灯&#xff0c;不仅仅是一次简单的操作&#xff0c;更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

Java技术栈 —— 如何把项目部署到公网?

如何把项目部署到公网&#xff1f; 一、准备工作1.1 获得一台云服务器1.2 安装SSH客户端 二、云服务器部署2.1 配置云服务器2.2 使用nginx部署1个或多个前端项目 三、访问测试四、访问控制 平常大部分人都是本地写写项目&#xff0c;然后通过localhost的方式去访问&#xff0c;…

春秋杯-WEB

SSTI 可以看到主页那里有个登录测试之后为ssti {{4*4}} fenjing梭哈即可得到payload {{((g.pop.__globals__.__builtins__.__import__(os)).popen(cat flag)).read()}}file_copy 看到题目名字为file_copy&#xff0c; 当输入路径时会返回目标文件的大小&#xff0c; 通…

基于微信小程序教学辅助系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(六)

文章目录 一、考试管理模块实现1、添加考试功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、考试管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码下载…

计算机网络 (43)万维网WWW

前言 万维网&#xff08;World Wide Web&#xff0c;WWW&#xff09;是Internet上集文本、声音、动画、视频等多种媒体信息于一身的信息服务系统。 一、基本概念与组成 定义&#xff1a;万维网是一个分布式、联机式的信息存储空间&#xff0c;通过超文本链接的方式将分散的信息…

如何学习数学 | 数学家如何思考

学习数学的关键在哪里&#xff1f; 原创 遇见数学 不少人面对数学都会觉得高深莫测&#xff0c;甚至非常枯燥乏味。 只有当你真正走入它的世界&#xff0c;才会发现里面蕴含着无尽的智慧和美感。要想推开这座数学的大门&#xff0c;需要的不仅仅是背公式&#xff0c;或者做一…

【Python通过UDP协议传输视频数据】(界面识别)

提示&#xff1a;界面识别项目 前言 随着网络通信技术的发展&#xff0c;视频数据的实时传输在各种场景中得到了广泛应用。UDP&#xff08;User Datagram Protocol&#xff09;作为一种无连接的协议&#xff0c;凭借其低延迟、高效率的特性&#xff0c;在实时性要求较高的视频…

ZNS SSD垃圾回收优化方案解读-2

四、Brick-ZNS 关键设计机制解析 Brick-ZNS 作为一种创新的 ZNS SSD 设计&#xff0c;聚焦于解决传统 ZNS SSDs 在垃圾回收&#xff08;GC&#xff09;过程中的数据迁移低效问题&#xff0c;其核心特色为存储内数据迁移与地址重映射功能。在应用场景中&#xff0c;针对如 Rock…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中&#xff0c;区块链技术如同一颗耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神&#xff0c;纷纷投身于区块链开发的领域&#xff0c;试…