前端技术搭建(动态图片)拖拽拼图!!(内含实现原理)

文章目录

  • 前端技术搭建(动态图片)拖拽拼图(内含实现原理)
  • 导言
  • 功能介绍
  • 效果演示链接(觉得不错的,请一键三连嘤嘤嘤)
  • 项目目录
    • 页面搭建
    • css样式设置
    • 工具函数
    • 游戏实现逻辑
  • 开源地址
  • 总结

前端技术搭建(动态图片)拖拽拼图(内含实现原理)

拼图封面.png

导言

两年半前,老师要求我们实现一个拼图拖拽游戏。
基于此,我重构了当年的代码,实现了更加丰富的游戏

功能介绍

动态拖拽拼图,是将以往的二维移动方块的方式,变成了三维移动方式,目标是将一张图片切割打乱,然后,重组为原图的游戏。

功能介绍

  • 等待用户输入玩家名,选择游戏难度
  • 期待用户上传自定义图片(支持gif,jpg,png等)
  • 开始游戏
  • 切割打乱图片
  • 用户拖拽拼图快完成图片
  • 烟花效果
  • 排行榜

image.png

image.png

image.png

效果演示链接(觉得不错的,请一键三连嘤嘤嘤)

通过gif动态图,我开发了一个动态图拖拽拼图网页游戏_哔哩哔哩_bilibili

项目目录

  • puzzle
    • css
      • index.css
    • pic
    • utils
      • confetti.js
      • index.js
    • index.html
    • index.js

页面搭建

首先实现游戏界面搭建,引入相关文件。

我将游戏分为三个部分

  • 游戏准备页面 (id=“start”)
  • 游戏界面 (id=“game_container”),游戏界面也分为三个部分
    1. 左边打乱拼图区域 id=“puzzle”
    2. 中间游戏目标完整图片id=“puzzle_map”
    3. 右边游戏目标id=“puzzle_destionation”
  • 游戏结束页面 (id=“end”)

index.html
界面布局
详情请看代码

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>拖拽拼图</title><script src="./utils/confetti.js"></script><link rel="stylesheet" href="css/index.css">
</head><body><div id="start" class=""><div class="box"><h1>欢迎玩家</h1><p>请创建的你的游戏信息</p><div class="form"><!-- 标题 --><div class="group"><label for="nickname">玩家昵称</label><input type="text" value="red润" id="nickname" name="nickname"></div><!-- 难度 --><div class="group"><label for="difficult">难度</label><select name="difficult" id="difficult"><option value="">请选择难度</option><option value="3">简单</option><option value="5">一般</option><option value="7">困难</option><option value="9">地狱</option><option value="11">天堂</option><option value="15">不要尝试的难度</option></select></div><!-- 放入图片 --><div class="group" id="drop"><div class="preview"><img src="./pic/upload.png" alt="放入拼图"><input type="file" name="pic" id="pic" accept="image/gif, image/jpeg ,image/png"></div><p>点击加号(选择你要放入的图片)</p></div><div class="group"><button name="submit">开始(请先上传图片)</button></div></div></div></div><div id="game_container" class="hidden"><span>用户名</span><div id="timer"><span>00:00</span></div><div id="puzzle_container"><div id="puzzle"></div><div id="puzzle_map"></div><div id="puzzle_destionation"></div></div><div class="buttons"><button class="stop">暂停</button><button class="restart">重新开始</button></div></div><div id="end" class="hidden"><div class="box" style="overflow: scroll;"><h3>拼图完成</h3><p>游戏胜利!</p><table><thead><tr><th>排名</th><th>难度</th><th>用户名</th><th>游戏时间</th></tr></thead><tbody><tr><td>1</td><td>不要尝试的难度</td><td>red润</td><td>11:11::23</td></tr></tbody></table><button onclick="document.querySelector('#end').classList.add('hidden'),document.querySelector('#start').classList.remove('hidden')">再来亿遍</button></div></div><script type="module">import Main from "./index.js"new Main()</script>
</body></html>

css样式设置

index.css 布局样式 详细请看代码

* {margin: 0;padding: 0;/* 比如输入框选中时候的边框 */outline: none;font-family: "Arial", sans-serif;color: #282828;/* 下划线 */text-decoration: none;/* 列表前面的 点 */list-style-type: none;box-sizing: border-box;
}html,
body {width: 100%;height: 100%;background-color: black;background: url("../pic/坤坤1.gif");background-size: 100% 100%;
}.hidden {display: none !important;
}/* 公用样式 */
#start {width: 100%;height: 100%;position: fixed;
}#end {width: 100%;height: 100%;position: fixed;mix-blend-mode:luminosity;
}.box {border-radius: 15px;padding: 40px;margin: 40px 40px;width: calc(100% - 80px);height: calc(100% - 80px);text-align: center;background-color: #F2F2F2;
}/* 游戏开始 */
#start .group {margin-top: 20px;
}#start .group input,
#start .group select {width: 99%;height: 40px;line-height: 40px;text-align: center;
}#start .group label {text-transform: uppercase;font-size: 15px;text-align: left;
}#start .group button {width: 100%;height: 60px;
}/* 选择上传图片功能 */
#start #drop {display: flex;flex-direction: row;width: 100%;height: 100px;line-height: 100px;text-align: center;border: dotted 1px rgba(0, 0, 0, 0.2);
}#start #drop p {width: calc(100% - 100px);
}#start .preview {position: relative;background-color: red;width: 100px;height: 100px;
}#start .preview img {position: absolute;width: 100px;height: 100px;left: 0;
}#start .preview input {left: 0;top: 0;width: 100px;height: 100px;position: absolute;opacity: 0;
}/* 游戏内容区域 */
#game_container {width: 100%;height: 100%;background-color: #009BBC;padding: 70px 50px 50px;text-align: center;}#game_container>span {display: inline-block;height: 30px;line-height: 30px;width: 100%;background-color: white;;
}#game_container #timer span {display: inline-block;width: 100%;height: 30px;line-height: 30px;background-color: #004D5E;
}/* 拼图区域 */
#puzzle_container {height: 300px;width: 100%;display: flex;flex-direction: row;
}#puzzle_container #puzzle {width: 300px;height: 300px;border: dotted 1px black;position: relative;
}#puzzle_container #puzzle_map {border-radius: 0;flex: 1;height: 300px;border: dotted 1px rgb(0, 0, 0);
}#puzzle_container #puzzle_destionation {width: 300px;height: 300px;position: relative;border: dotted 1px black;
}#game_container .buttons button {width: 100%;height: 30px;
}/* 游戏结束 */
#end {width: 100%;height: 100%;
}#end h3 {text-align: center;
}#end p {text-align: center;
}#end table {width: 100%;/* 共享边框 */border-collapse: collapse;
}#end table th,
td {padding: 10px;border: solid 1px rgb(0, 0, 0, 0.2);
}#end button {width: 100%;text-align: center;height: 50px;
}

工具函数

utils/index.js 工具函数 封装复用函数

export default class Utils {/*** 通过传入的文件,拿到文件数据流* @param {object} file 传入的文件* @returns {string} url 返回图片url*/static getUrlByFile(file) {let url = null;// 下面函数执行的效果是一样的,只是需要针对不同的浏览器执行不同的 js 函数而已if (window.createObjectURL != undefined) { // basicurl = window.createObjectURL(file);} else if (window.URL != undefined) { // mozilla(firefox)url = window.URL.createObjectURL(file);} else if (window.webkitURL != undefined) { // webkit or chromeurl = window.webkitURL.createObjectURL(file);}return url;}/*** 将秒转换为 天时分秒* @param {*} value 毫秒* @returns {string} str 格式化后的字符串*/static formatSeconds(value) {let s = value//秒let m = 0;//分let h = 0;//小时let d = 0;//天if (s > 60) {m = parseInt(s / 60)s = parseInt(s % 60)if (m > 60) {h = parseInt(m / 60)m = parseInt(m % 60)if (h > 24) {d = parseInt(h / 24)h = parseInt(h % 24)}}}let result = ''if (s > 0) {if (s < 10) {result = "0" + s + "秒"} else {result = s + "秒"}}if (m > 0) {if (m < 10) {result = "0" + m + "分" + ":" + result} else {result = m + "分" + ":" + result}}if (h > 0) {if (h < 10) {result = "0" + h + "时" + ":" + result} else {result = h + "时" + ":" + result}}if (d > 0) {if (d < 10) {result = "0" + d + "天" + ":" + result} else {result = d + "天" + ":" + result}}return result}/*** 只显示一个用户场景* @param {*} name */static showOne(that,name){// this.startEle.classList.remove("hidden")// this.gameContainerEle.classList.add("hidden")// this.endEle.classList.add("hidden")that[name].classList.remove('hidden')let names = ["startEle","gameContainerEle",'endEle']names.filter(item=>item!==name).forEach(item=>{that[item].classList.add('hidden')})}/*** 根据传入的数值,返回一个和数值长度大小相等的数组* @param {*} num * @returns {arr[]}*/static rM(num){let randomArr = []// 保存有序数组for(let a=0;a<num;a++){randomArr.push(a)}// 打乱有序数组randomArr.sort((a,b)=>Math.random()-0.5)return randomArr}
}

游戏实现逻辑

index.js 游戏实现完整逻辑 详情请看代码

import Utils from './utils/index.js';
export default class Main {constructor() {// 记录游戏时间this.time = 0;// 定时器对象this.timer = null;// 游戏是否暂停this.stop = false;// 游戏难度等级this.level = 3// 玩家昵称this.nickname = null// 拖拽拼图的宽高this.width = 300;this.height = 300;// 用户上传的图片文件this.file = null// 用户上传图片后转换为数据流 作为url路径this.url = null// start容器元素this.startEle = document.querySelector("#start");// game_container容器元素this.gameContainerEle = document.querySelector("#game_container")// end容器元素this.endEle = document.querySelector("#end")// start元素下面的imgthis.startImg = document.querySelector("#start img")// start元素下面的用户名this.startNickName = document.querySelector("#start #nickname")// start元素下面的等级this.startLevel = document.querySelector("#start #difficult")// start元素下面的开始按钮this.startBtn = document.querySelector("#start button")// start元素input上传文件元素this.startPic = document.querySelector("#start #pic")// game_container下面的timerthis.gameTimer = document.querySelector("#game_container #timer")// 暂停按钮this.gameStopBtn = document.querySelector("#game_container .stop")// 重新开始按钮this.gameRestartBtn = document.querySelector("#game_container .restart")// 左边拼图块this.puzzle = document.querySelector('#puzzle')// 中间拼图块this.puzzleMap = document.querySelector('#puzzle_map')// 右边拼图块this.puzzleDestionation = document.querySelector("#puzzle_destionation")this.init()}init() {// 烟花this.jsConfetti = new JSConfetti()const addFire = (i = 1) => {for (i; i > 0; i--) {setTimeout(() => {this.jsConfetti.addConfetti()}, i * 500)}}addFire(11)console.log("游戏初始化");// 初始化排行榜this.initRank()// 显示开始界面,隐藏其他界面Utils.showOne(this, "endEle")// 禁用开始按钮this.startBtn.disabled = truethis.startBtn.style.cursor = "not-allowed";// 监听图片上传this.addEventListenerStartPicChange()// 监听开始游戏按钮this.addEventListenerStartBtn()// 监听是否点击游戏暂停按钮this.addEventListenerIsStop()// 监听是否重新游戏this.gameRestartBtn.addEventListener("click", () => {this.restartGame()})}initRank() {let tbody = document.querySelector("table>tbody")let rankArr = JSON.parse(localStorage.getItem("ranking"))let objs = []objs.push(`<tr><td>1</td><td>不要尝试的难度</td><td>red润</td><td>4天:3时:5分:18秒</td></tr>`)for (const key in rankArr) {let obj = rankArr[key]parseInt(obj.level)if (obj.level == 3) {obj.level = "简单"} else if (obj.level == 5) {obj.level = "一般"} else if (obj.dif == 7) {obj.level = "困难"} else if (obj.level == 9) {obj.level = "地狱"} else if (obj.level == 11) {obj.level = "天堂"} else if (obj.level == 15) {obj.level = "不要尝试的难度"}let node = `<tr><td>${parseInt(key) + 2}</td><td>${obj.level}</td><td>${obj.name}</td><td>${obj.time}</td></tr>`objs.push(node)}tbody.innerHTML = objs}// 监听用户是否点击上传图片,将上传的图片存储下来addEventListenerStartPicChange() {// 注意this的指向this.startPic.addEventListener("change", (e) => {// 存储用户上传的图片this.file = e.target.files[0];// 转换this.url = Utils.getUrlByFile(this.file);if (this.url !== null) {this.startBtn.disabled = falsethis.startBtn.style.cursor = "pointer";this.startImg.src = this.urlthis.initGameContainer()}})}// 监听开始游戏按钮addEventListenerStartBtn() {this.startBtn.addEventListener('click', () => {this.initGameContainer()})}// 监听 暂停按钮 点击addEventListenerIsStop() {this.gameStopBtn.addEventListener("click", () => {this.stop = !this.stopif (this.stop === false) {this.startCountTime()this.gameStopBtn.innerHTML = "暂停游戏"} else {this.stopCountTime()this.gameStopBtn.innerHTML = "继续游戏"}})}// 开始定时startCountTime() {if (this.timer) clearInterval(this.timer)this.timer = setInterval(() => {this.time++this.gameTimer.innerHTML = Utils.formatSeconds(this.time)}, 1000)}// 暂停stopCountTime() {if (this.timer) clearInterval(this.timer)}// 重新游戏restartGame() {window.location.reload()}// 初始化游戏地图initGameContainer() {if (!this.startNickName.value || !this.startLevel.value) {alert("用户名或者游戏难度不能为空");return;}// 存储用户选择的难度等级this.level = this.startLevel.value// 存储玩家名字this.nickname = this.startNickName.value// 显示游戏地图,隐藏其他地图Utils.showOne(this, "gameContainerEle")// 初始化拼图this.initPuzzle()// 开始计时this.startCountTime()}// 初始化拼图initPuzzle() {// 左边this.puzzle.style.background = `url(${this.url})`this.puzzle.style.backgroundSize = "100% 100%";// 中间this.puzzleMap.style.background = `url(${this.url})`this.puzzleMap.style.backgroundSize = "100% 100%";// 右边this.puzzleDestionation.style.background = `url(${this.url})`this.puzzleDestionation.style.backgroundSize = "100% 100%";// 创建左边拖拽this.createPuzzle(this.puzzle)// 创建右边接收区this.createPuzzle(this.puzzleDestionation)}// 根据传入的puzzle,创建拖拽元素createPuzzle(ele) {// 存储打乱后的divlet arr = [];// 给每个div设置一个唯一idlet id_num = 0;// 每行/每列 puzzle块的数量 300/3 = 10let ppx = `${Math.floor(this.width / this.level)}`;// 根据用户选择的难度,产生对应的随机数组 3*3let randomNum = Utils.rM(this.level);for (let i = 0; i < this.level; i++) {for (let j = 0; j < this.level; j++) {let div = document.createElement("div");div.style.backgroundRepeat = "no-repeat";div.style.zIndex = '100'div.style.width = ppx + 'px'div.style.height = ppx + 'px'div.style.position = 'absolute'if (ele.id === 'puzzle') {div.style.border = `${1}px solid yellow`// 打乱拼图位置div.style.top = `${randomNum[j] * ppx}px`div.style.left = `${randomNum[i] * ppx}px`div.style.background = `url(${this.url})`div.style.boxSizing = 'border-box'div.style.backgroundSize = "300px 300px"div.draggable = true// 虽然位置是乱的,但是id是正常的div.id = id_num// 水平/垂直div.style.backgroundPosition = `-${(j * ppx)}px -${(i * ppx)}px`arr.push(div)} else {div.style.border = `${1}px solid pink`//不能打乱图片顺序div.style.top = (i * ppx) + 'px'div.style.left = (j * ppx) + 'px'div.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'div.className = id_numdiv.id = id_num + "1"arr.push(div)}id_num++;}}// 设置拖拽事件和放置事件this.setPuzzleEvent(ele, arr)}setPuzzleEvent(ele, arr) {// 左边拼图拖拽的时候,设置idif (ele.id === 'puzzle') {for (let i = 0; i < arr.length; i++) {ele.appendChild(arr[i])arr[i].ondragstart = (e) => {e.dataTransfer.setData("Id", e.target.id)}}} else {for (let i = 0; i < arr.length; i++) {ele.appendChild(arr[i])arr[i].ondragover = (e) => {e.preventDefault()}let that = thisarr[i].ondrop = function (e) {let leftId = e.dataTransfer.getData("Id");let leftDiv = document.getElementById(leftId);leftDiv.style.top = 0;leftDiv.style.left = 0;// 将拖拽方块,从左边放到右边this.appendChild(leftDiv);// 右边的所有元素节点let allNodes = this.parentNode.childNodes;that.isWin(allNodes)}}}}// 是否胜利isWin(allNodes) {// 判断游戏是否胜利let allChild = []// 存储右边元素的儿子节点的idallNodes.forEach(element => {let child = element.childNodes[0]if (child) {allChild.push(child.id)}});// 长度要相等,然后,判断是否完全重合if (allNodes.length === allChild.length) {for (let i = 0; i < allChild.length; i++) {if (i == allChild[i]) {alert("游戏胜利")this.joinRank()return}}} else {console.log("加油马上就成功了");}}// 加入排行榜joinRank() {let rankArr = []if (localStorage.getItem("ranking")) {rankArr = JSON.parse(localStorage.getItem("ranking"))}let obj = {name: this.nickname,level: this.level,time: Utils.formatSeconds(this.time)}rankArr.unshift(obj)localStorage.setItem("ranking", JSON.stringify(rankArr))this.stopCountTime();this.time = 0;this.restartGame()}}

开源地址

  • 开源地址:zou-hong-run/puzzle: 拖拽拼图 (github.com)
  • 项目在线体验地址(电脑体验,手机尚未适配):https://zou-hong-run.github.io/puzzle/new_version

总结

  • 通过本次编写代码体验,加强了拖拽api的理解,面向对象的理解
  • 还有很多不足,请大家指教
  • 大佬们觉得不错的话,请一键三连呀

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot整合JavaMail

SpringBoot整合JavaMail 简单使用-发送简单邮件 介绍协议 导入坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>添加配置 spring:mail:host: smtp.qq.co…

Wonderful Sql

Wonderful Sql 一. 初识数据库 练习题 1.1 编写一条 CREATE TABLE 语句&#xff0c;用来创建一个包含表 1-A 中所列各项的表 Addressbook &#xff08;地址簿&#xff09;&#xff0c;并为 regist_no &#xff08;注册编号&#xff09;列设置主键约束 表1-A 表 Addressbook…

java代码审计6之ssrf

文章目录 1、java支持的网络请求协议&#xff1a;2、Java 中能发起⽹络请求的类2.1、仅⽀持 HTTP/HTTPS 协议的类2.2、⽀持 sun.net.www.protocol 所有协议的类2.3、审计关键词 3、靶场3.1、漏洞代码13.2、ftp协议读取技巧3.3、无回显之探测内网3.4、无回显之探测文件 之前的文…

【数据分析专栏之Python篇】二、Jupyer Notebook安装配置及基本使用

文章目录 前言一、Jupter Notebook是什么1.1 简介1.2 组成部分1.3 Jupyter Notebook的主要特点 二、为什么使用Jupyter Notebook?三、安装四、Jupyter Notebok配置4.1 基本配置4.2 配置开机自启与后台运行4.3 开启代码自动补全 五、两种键盘输入模式5.1 编辑模式5.2 命令模式5…

探究Spring Bean的六种作用域:了解适用场景和使用方式

这里写目录标题 单例&#xff08;Singleton&#xff09;作用域&#xff1a;原型&#xff08;Prototype&#xff09;作用域&#xff1a;请求&#xff08;Request&#xff09;作用域&#xff1a;会话&#xff08;Session&#xff09;作用域&#xff1a;全局&#xff08;applicati…

4-Linux组管理和权限管理

Linux组管理和权限管理 Linux组的基本介绍文件/目录的所有者组的创建文件/目录所在的组其它组改变用户所在的组权限的基本介绍第0-9位说明rwx权限详解rwx 修饰文件时rwx修饰目录时 修改权限第一种方式&#xff1a;、-、 变更权限第二种方式&#xff1a;通过数字变更权限 修改文…

安全学习DAY07_其他协议抓包技术

协议抓包技术-全局-APP&小程序&PC应用 抓包工具-Wireshark&科来分析&封包 TCPDump&#xff1a; 是可以将网络中传送的数据包完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤&#xff0c;并提供and、or、not等逻辑语句来帮助你去掉无用…

疾风计划-程序设计基础-期末考试-05

擀面皮 有一块1x1的方形面团&#xff08;不考虑面团的厚度&#xff09;&#xff0c;其口感值为0。擀面师傅要将其擀成一个N x M&#xff08;纵向长N&#xff0c;横向宽M&#xff09;的面皮。师傅的擀面手法娴熟&#xff0c;每次下手&#xff0c;要么横向擀一下&#xff08;使得…

深入理解Linux 内核追踪机制

Linux 存在众多 tracing tools&#xff0c;比如 ftrace、perf&#xff0c;他们可用于内核的调试、提高内核的可观测性。众多的工具也意味着繁杂的概念&#xff0c;诸如 tracepoint、trace events、kprobe、eBPF 等&#xff0c;甚至让人搞不清楚他们到底是干什么的。本文尝试理清…

centos下安装ftp-读取目录列表失败-

1.下载安装ftp服务器端和客户端 #1.安装yum -y install vsftpdyum -y install ftp #2.修改配置文件vim /etc/vsftpd.conflocal_enablesYESwrite_enableYESanonymous_enableYESanon_mkdir_write_enableYES //允许匿名用户在FTP上创建目录anon_upload_enableYES //允许匿名用户…

B074-详情富文本 服务上下架 高级查询 分页 查看详情

目录 服务详情修改优化ProductServiceImplProduct.vue 详情数据-富文本-vue-quill-editor使用步骤测试图片的访问方式富文本集成fastDfs 后台服务上下架&#xff08;批量&#xff09;前端开始后端完成ProductControllerProductServiceImplProductMapper 前台展示上架前端开始后…

使用docker 部署自己的chatgpt

直接docker部署 docker run --name chatgpt-web -d -p 3002:3002 --env OPENAI_API_KEYyour_api_key chenzhaoyu94/chatgpt-web:latestDocker compose部署 version: 3services:app:image: chenzhaoyu94/chatgpt-web # 总是使用 latest ,更新时重新 pull 该 tag 镜像即可ports…

NLP(六十一)使用Baichuan-13B-Chat模型构建智能文档问答助手

在文章NLP&#xff08;六十&#xff09;Baichuan-13B-Chat模型使用体验中&#xff0c;我们介绍了Baichuan-13B-Chat模型及其在向量嵌入和文档阅读上的初步尝试。   本文将详细介绍如何使用Baichuan-13B-Chat模型来构建智能文档问答助手。 文档问答流程 智能文档问答助手的流…

【*1900 图论】CF1328 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 注意到题目的性质&#xff1a;满足条件的路径个数是极少的&#xff0c;因为每个点离路径的距离<1 先考虑一条链&#xff0c;那么直接就选最深那个点作为端点即可 为什么&#xff0c;因为我们需要遍历所有点…

3.安装kubesphere

1.本地存储动态 PVC # 在所有节点安装 iSCSI 协议客户端&#xff08;OpenEBS 需要该协议提供存储支持&#xff09; yum install iscsi-initiator-utils -y # 设置开机启动 systemctl enable --now iscsid # 启动服务 systemctl start iscsid # 查看服务状态 systemctl status …

将数据转二进制流文件,用PostMan发送二进制流请求

一、将byte数组转二进制流文件&#xff0c;并保存到本地 byte [] oneshotBytesnew byte[]{78,-29,51,-125,86,-105,56,82,-94,-115,-22,-105,0,-45,-48,-114,27,13,38,45,-24,-15,-13,46,88,-90,-66,-29,52,-23,40,-2,116,2,-115,17,36,15,-84,88,-72,22,-86,41,-90,-19,-58,19…

Opencv-C++笔记 (13) : opencv-图像卷积一(均值、中值、高斯、双边滤波)与 边缘处理

文章目录 一、概述图像滤波1.1、均值滤波1.2中值滤波1.3、高斯滤波1.4、双边滤波1.5、方框滤波 二、自定义掩码三、边缘处理四、Sobel算子五、Scharr算子六、拉普拉斯算子十、Canny算法 一、概述图像滤波 头文件 quick_opencv.h&#xff1a;声明类与公共函数 #pragma once #i…

13.Netty源码之Netty中的类与API

highlight: arduino-light ServerBootstrap Bootstrap 意思是引导&#xff0c;一个 Netty 应用通常由一个 Bootstrap 开始&#xff0c;主要作用是配置整个 Netty 程序&#xff0c;串联各个组件&#xff0c;Netty 中ServerBootstrap 是服务端启动引导类。 java //泛型 AbstractB…

Vue2到3 全套学习内容(持续更新)

Vue 初次上手 1. Vue 概念 概念: Vue 是一个用于 构建用户界面 的 渐进式 框架 ①构建用户界面&#xff1a;基于数据动态渲染出用户看到的页面 ②渐进式&#xff1a;循序渐进 Vue的两种使用方式: ①Vue 核心包开发 场景: 局部 模块改造 ②Vue核心包&Vue插件工程化开发…

C++-----list

本期我们来讲解list&#xff0c;有了string和vector的基础&#xff0c;我们学习起来会快很多 目录 list介绍 ​编辑 list常用接口 insert erase reverse sort merge unique remove splice 模拟实现 基础框架 构造函数 push_back 迭代器 常见问题 const迭代器 …