首页
学习
关于
友链
Search
1
小程序 蓝牙连接(出现的问题和一些解决方法)
322 阅读
2
颜色空间:RGB、HSV和HSL
156 阅读
3
小程序_连接蓝牙设备根据平台去打开定位权限
142 阅读
4
小程序 加快安卓手机向蓝牙设备发送大数据
96 阅读
5
侧边菜单切换的显示与隐藏,图标的 + 与 -
92 阅读
全部
感想
旅行
生活
学习
登录
Search
标签搜索
css
javascript
jquery
html
小程序
github
图床
假期
发布订阅
typecho
第一次
未来
快乐与忧伤
努力
奋斗
PicGo
倒计时
元旦
svg
vue
逸曦穆泽
累计撰写
35
篇文章
累计收到
22
条评论
首页
栏目
全部
感想
旅行
生活
学习
页面
学习
关于
友链
搜索到
35
篇与
全部
的结果
2022-12-17
小程序_图片转canvas,上传和rgb888转rgb565发送到设备
序: 小程序需要将图片上传到蓝牙设备,那么图片要转为二进制数据,转为二进制的图片数据不能过大,就要裁剪图片,因为要尽量减少图片的二进制数据,要将图片的rgb888转为rgb565,也就是24位缩小为16位数据;例如:100像素*100像素的图片,就有1万个点,一个点包含rgba四个数,只需要rgb这三个数,rgb三个数各包含8位(也就是二进制,为rgb888),rgb888为三个字节,rgb565为两个字节,数据量传输就少了三分一,但也有几十K的数据了,分240个字节每包发送完也要十秒左右;如果要上传,上传到后端的路径要是临时路径才可以,不能是本地路径,所以要使用 canvas 转一下得到 tempFilePath 的临时路径,一、图片渲染为 canvas 得到临时路径,并上传// 选择本地图片渲染成 canvas locationImg(e) { let imgUrl = e.currentTarget.dataset.img; let that = this; gbImgComStr = ""; wx.createSelectorQuery().select('#canvasImg').fields({ node: true, size: true }).exec((res) => { const canvas = res[0].node; const ctx = canvas.getContext('2d'); var dpr = wx.getSystemInfoSync().pixelRatio // 设备像素比 canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr ctx.scale(dpr, dpr) const img = canvas.createImage(); img.onload = () => { ctx.drawImage(img, 0, 0, 200, 200); wx.canvasToTempFilePath({ x: 0, y: 0, width: 200, height: 200, destWidth: 200, destHeight: 200, canvas: canvas, fileType: "jpg", quality: .8, success(res) { that.initImgData(res.tempFilePath); // 使用服务器 } }) } img.src = imgUrl; }) // console.log(imgUrl) }, // 图片上传到服务器 initImgData(imgUrl) { let that = this; let gbImgPath = ""; wx.uploadFile({ url: apiUrl+'/imgUpload', //你的后端上传路径 filePath: imgUrl, name: "imgPath", // 键值key header: { "content-type": "multipart/form-data"}, success: function (res) { if (res.statusCode == 200) { gbImgPath = JSON.parse(res.data).imgPath; // 存放到服务器上的图片路径 } }, fail: function (err) { wx.showToast({ title: "上传失败", icon: "none", duration: 2000 }) }, }) // 图片回显 或 gbImgPath that.setData({ imgPath: imgUrl }) },后端接口(PHP)://对应的文件夹 public function dirFile($name){ $dirName = "store/".$name."/".date("Ym"); if(!file_exists($dirName)){ mkdir(app()->getRootPath().'public/'.$dirName,0777,true); } return $dirName; } // 图片处理 function imgUpload(){ if(request()->isPost()){ $dirName = $this -> dirFile('image'); $file = $_FILES['imgPath']; // 获取小程序传来的图片 if(is_uploaded_file($file['tmp_name'])) { $type = $file["type"];//文件类型 如:image/png $ext = strrchr($type, '/');//切割字符串 //类型判断 if (in_array($ext, ['/jpeg', '/jpg', '/png', '/svg', '/gif','ico'])) { $filePrefix1 = strstr($file["name"], '.', true);// 文件名前缀 无.png $filestr = date("Ymdhis").$filePrefix1; // 避免同一时间调用该方法时产生同一个文件名 $fileExt1 = strstr($file["name"], '.'); // 获取 .png $fileName = $dirName . "/" . md5($filestr) . $fileExt1; //拼接文件路径 //判断文件是否存在 // if (file_exists($fileName)) { // return json(["statusCode" => 200,"msg"=>"exist","imgPath" => $fileName]); // } else { //保存文件 ($_FILES["文件名"]["tmp_name"],newPath),(旧路径,新路径) move_uploaded_file($file["tmp_name"], $fileName); return json(["statusCode" => 200,"msg"=>"success","imgPath" => $fileName]); // } } return json(["statusCode" => 402,"msg"=>"format error"]); } return json(["statusCode"=>401,"msg"=>"file error"]); } return json(["statusCode"=>400,"msg"=>"request error"]); }二、在小程序上将图片数据rgb888转为rgb565var gbImgComStr = ""; // 图片:16进制补零 function imgHexFill(hexStr) { let len = hexStr.length; var map = { 1: "000", 2: "00", 3: "0" } if (map[len]) { hexStr = map[len] + hexStr; } return hexStr; } // 上为 Page 外,下为 Page 内 // 图片画成 canvas 获取数据 initImgData565: async function(imgUrl) { return new Promise((resolve, reject) => { let that = this; imgLimitNum = 0; wx.createSelectorQuery().select('#canvasImg').fields({ node: true, size: true }).exec((res) => { const canvas = res[0].node; const ctx = canvas.getContext('2d'); // var dpr = wx.getSystemInfoSync().pixelRatio // 设备像素比 var dpr = 1; canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr // ctx.scale(dpr, dpr) let sideLen = 100; ctx.fillRect(0, 0, sideLen, sideLen); const img = canvas.createImage(); img.onload = () => { ctx.drawImage(img, 0, 0, sideLen, sideLen); var imageData = ctx.getImageData(0, 0, sideLen, sideLen).data; // console.log(imageData.length) var rgbStr = ""; var rgb = 0; var rgb565 = 0; var w = 0; var h = 0; // 逐列式 (逐行式则是Z扫描) for (var w = 0; w < sideLen; w++) { for (var h = 0; h < sideLen; h++) { var offset = (h*sideLen + w)*4; var red = imageData[offset]; var green = imageData[offset + 1]; var blue = imageData[offset + 2]; rgb = 0xff000000 | (red << 16) | (green << 8) | blue; rgb565 = ((rgb & 0xf80000) >> 8) | ((rgb & 0xfc00) >> 5) | ((rgb & 0xf8) >> 3) rgbStr += imgHexFill(rgb565.toString(16)); } } gbImgComStr = rgbStr.toUpperCase(); imgUrl != "" ? resolve() : reject(); } img.src = imgUrl; }) }) },由于数据过大,这些数据还要分包发送到蓝牙设备,首先,要发第一包数据告诉设备要发图片的指令了,可以加入长度,这个要和设备那边沟通,分包发送还不能全部直接发,不然蓝牙设备很容易造成丢包的,小程序发完了,设备那边可能才获取十分之一呢,要分20、30包发完后再发一个确定指令,如果返回正确的指令则继续分20、30包发下去再发一个确定指令,然后重复发完为止;部分代码:// 图片_下个数据包指令 imgNextCmd: async function(){ let that = this; let sData = that.data; let comStr = "", roleData = "", command = ""; let rlt = ""; let packageNum = 30; // 连续发送包的个数 var rowSum = ((imgPackageSum - imgIndex) >= packageNum) ? (imgIndex + packageNum) : imgPackageSum; for (let row = imgIndex; row < rowSum; row++) { comStr = gbImgComStr.substr((row)*(imgCharLen-10),(imgCharLen-10)); roleData = "AC" + decToHexLenFill(row+1) + decToHex(comStr.length/2) + comStr; let res = new Uint8Array(roleData.match(/[\da-f]{2}/gi).map(function (h) { return parseInt(h, 16) })); command = roleData + arrSumCheck(res); imgIndex += 1; // await sleep(50); rlt = await that.sendCom(command, sData.deviceId, sData.serviceId, sData.characteristicId); if (rlt == "success") { // 包确认 if(row == (rowSum-1)){ // console.log(">>> sure",rowSum)// 成功 let sureCom = "BCxxxx"+decToHexLenFill(row+1); let cs = new Uint8Array(sureCom.match(/[\da-f]{2}/gi).map(function (h) { return parseInt(h, 16) })); let sureCommand = sureCom + arrSumCheck(cs); that.writeBLECharacteristicValue(sureCommand); } } } if(rowSum == imgPackageSum && imgLimitNum == 0){ imgLimitNum = 1; let endCom = "xxx"; // 传输完毕 that.writeBLECharacteristicValue(endCom); } },彩蛋: 一般一个包只能发20个字节,你觉得一张150*150的图片数据发完需要多久?要两分钟左右吧,这个还没考虑中途断连等情况呢!你觉得你是用户,你会接受吗?所以,可以先获取一下mtu是很有必要的,一般Android的是23(包含头部3个字节信息),iOS的是512,有部分Android手机是没有mtu值的,只能落空默认值了,Android可以协商mtu值 wx.setBLEMTU ,你可以一个包发256、300个字节,看你需求,过大会产生一些问题,并且每包发送也可以设置一下延迟多少毫秒,也可以避免传输过程中断连问题。
2022年12月17日
52 阅读
0 评论
0 点赞
2022-11-13
小程序 加快安卓手机向蓝牙设备发送大数据
序: 小程序要将图片数据传到蓝牙设备上,几十上百K的图片数据相对于蓝牙设备来说是很大的,正常20个字节发送完到设备要一两分钟,如果与安卓协商mtu长度后,则可以达到十几二十多秒左右,安卓低机型不支持。和安卓协商mtuvar imgCharLen = 240; // 图片有效数据长度,iOS:240(120个字节),Android:40(20个字节) var platform = true; // true_ios,false_android onLoad(){ const res = wx.getSystemInfoSync(); platform = res.platform == "ios" ? true : false; } onShow() { // 连上设备 if(app.globalData.connected){ // 和安卓协商mtu if(!platform){ wx.setBLEMTU({ deviceId: app.globalData.deviceId, mtu: 240, success:(res)=>{ if(res.errCode == 0){ imgCharLen = 240; // mtu:240 }else{ imgCharLen = 40; } } }) } } }app.globalData.connected 这个是全局变量来着,也就是设备连接之后才协商的当然,也可以根据你的实际需要来设置,ios的mtu默认是512,Android的mtu默认是23.
2022年11月13日
96 阅读
2 评论
0 点赞
2022-10-15
小程序_连接蓝牙设备根据平台去打开定位权限
全局定义和使用:全局获取一次,适用单个或多个页面去使用,避免多次频繁去获取接口信息。app.jsonLaunch() { const res = wx.getSystemInfoSync(); this.globalData.platform = res.platform != "ios" ? true : false; }, globalData: { platform: false, // 默认 ios,其他平台需要权限 }xxx.js 使用const app = getApp(); var platform = false; // 平台:iOS_false,其他_true Page({ onLoad: function (options) { let that = this; platform = app.globalData.platform if(platform){ that.getLocation(); } } })在单独页面使用:单个页面获取与使用,在单页可以单次或多次使用,方便直接。const app = getApp(); var platform = false; // 平台:iOS_false,其他_true Page({ onLoad: function (options) { let that = this; const res = wx.getSystemInfoSync() platform = res.platform != "ios" ? true : false; if(platform){ that.getLocation(); } }, /** 获取定位信息 */ getLocation: function () { // 获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限 wx.getSetting({ success: function (res) { if(res.authSetting['scope.userLocation'] != undefined && res.authSetting['scope.userLocation'] != true){ wx.showModal({ title: '是否授权当前位置', content: '需要获取你的地理位置,请确认授权,否则无法获蓝牙', success: function(mres){ if(mres.confirm){ wx.openSetting({ success (authData) { if(authData.authSetting['scope.userLocation'] == true){ wx.showToast({ title: '授权成功', icon: "success", duration: 1000 }) }else{ wx.showToast({ title: '授权失败', icon: "error", duration: 1000 }) } } }) }else if(mres.cancel){ wx.showToast({ title: '授权失败', icon: "error", duration: 1000 }) } } }) }else{ // 当前位置 wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 wx.getLocation({ type: 'wgs84', success: function (res) { app.hintLog('打开地理位置','') }, }) } }, }) }, })可能有很多人有疑惑,为什么Android手机需要打开定位权限,其实不是的,Android手机需要打开定位权限的只是部分手机而已,并不是全部,如果可以,你可以根据部分手机去过滤掉也是可行的。
2022年10月15日
142 阅读
2 评论
0 点赞
2022-09-18
JS基本特效 -- 常见40个常用的js页面效果图
1、将彻底屏蔽鼠标右键(oncontextmenu="window.event.returnValue=false")<table border oncontextmenu=return(false)><td>no</table> // 可用于Table2、取消选取、防止复制<body onselectstart="return false"> 3、不准粘贴onpaste="return false"4、防止复制oncopy="return false;" oncut="return false;" 5、IE地址栏前换成自己的图标 <link rel="Shortcut Icon" href="favicon.ico"> 6、可以在收藏夹中显示出你的图标<link rel="Bookmark" href="favicon.ico">7、关闭输入法<input style="ime-mode:disabled">8、永远都会带着框架<script language="JavaScript"><!--if (window == top)top.location.href = "frames.htm"; //frames.htm为框架网页 --> </script>9、防止被人frame<script language="javascript" > <!-- if (top.location != self.location)top.location=self.location;--> </script>10、网页将不能被另存为<noscript><iframe src="/blog/*.html>";</iframe></noscript>11、查看网页源代码<input type=button value="查看网页源代码" onclick="window.location='view-source:' + 'http://www.williamlong.info'">12、删除时确认<a href="javascript:if(confirm('确实要删除吗?'))console.log('删除')">删除</a>13、取得控件的绝对位置//Javascript <script language="Javascript"> function getIE(e){ var t=e.offsetTop; var l=e.offsetLeft; while(e=e.offsetParent) alert("top="+t+"/n left="+l); } </script> <script language="VBScript"> function getIE() dim t,l,a,b set a=document.all.img1 t=document.all.img1.offsetTop l=document.all.img1.offsetLeft while a.tagName<>"BODY" set a = a.offsetParent t=t+a.offsetTop l=l+a.offsetLeft wend msgbox "top="&t&chr(13)&"left="&l,64,"得到控件的位置" end function </script>14、光标是停在文本框文字的最后<script language="javascript"> function lightFocus(){ var e = event.srcElement; var r =e.createTextRange(); r.moveStart("character",e.value.length); r.collapse(true); r.select(); } </script> <input name="test" value="333" onfocus="lightFocus()" />15、判断上一页的来源 javascript: document.referrer16、最小化、最大化、关闭窗口 <object id="min" classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11"> <param name="Command" value="Minimize"> </object> <object id="max" classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11"> <param name="Command" value="Maximize"> </object> <object id="close" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"> <param name="Command" value="Close"> </object> <input type="button" value="最小化" onclick="min.tabMin()"> <input type="button" value="最大化" onclick="max.tabMax()"> <input type="button" value="关闭" onclick="close.tabClose()">17、屏蔽功能键Shift,Alt,Ctrl<script> function look(){ if(event.shiftKey){} alert("禁止按Shift键!"); //可以换成ALT CTRL } document.onkeydown=look; } </script>18、网页不会被缓存 <META HTTP-EQUIV="pragma" CONTENT="no-cache"> <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate"> <META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT"> 或者<META HTTP-EQUIV="expires" CONTENT="0">19、怎样让表单没有凹凸感?<input type=text style="border:1 solid #000000">或 <input type=text style="border-left:none; border-right:none; border-top:none; border-bottom:1 solid #000000"></textarea>20、<div><span>&<layer>的区别? <div>(division)用来定义大段的页面元素,会产生转行 <span>用来定义同一行内的元素,跟<div>的唯一区别是不产生转行 <layer>是ns的标记,ie不支持,相当于<div>21、让弹出窗口总是在最上面: <body onblur="this.focus();">22、不要滚动条? // 让竖条没有: <body style="overflow:scroll;overflow-y:hidden"> </body> // 让横条没有: <body style="overflow:scroll;overflow-x:hidden"> </body> // 两个都去掉?更简单了 <body scroll="no"></body>23、怎样去掉图片链接点击后,图片周围的虚线?<a href="#" onFocus="this.blur()"><img src="/xxx/logo.jpg" border=0></a>24、电子邮件处理提交表单 <form name="form1" method="post" action="mailto:****@***.com" enctype="text/plain"> <input type=submit> </form>25、在打开的子窗口刷新父窗口的代码里如何写? window.opener.location.reload()26、如何设定打开页面的大小 <body onload="top.resizeTo(300,200);"> 打开页面的位置<body onload="top.moveBy(300,200);">27、在页面中如何加入不是满铺的背景图片,拉动页面时背景图不动<style> body{background-image:url(/blog/logo.gif); background-repeat:no-repeat; background-position:center;background-attachment: fixed} </style>28、检查一段字符串是否全由数字组成<script language="Javascript"> function checkNum(str){return str.match(//D/)==null} alert(checkNum("1232142141")) alert(checkNum("123214214a1")) </script>29、获得一个窗口的大小document.body.clientWidth; document.body.clientHeight30、怎么判断是否是字符 if (/[^/x00-/xff]/g.test(s)){ alert("含有汉字"); } else { alert("全是字符"); }31、TEXTAREA自适应文字行数的多少 <textarea rows=1 name=s1 cols=27 onpropertychange="this.style.posHeight=this.scrollHeight"></textarea>32、日期减去天数等于第二个日期<script language=Javascript> function test(d,td){ //可以加上错误处理 var a = new Date(d); a = a.valueOf(); a = a - td * 24 * 60 * 60 * 1000; b = new Date(a); alert(b.getFullYear() + "年" + (b.getMonth() + 1) + "月" + b.getDate() + "日") } test("12/23/2002",2); </script>33、选择了哪一个Radio<html> <script language="vbscript"> function checkme() // 点击切换 } </script> <body> <input name="radio1" type="radio" value="style" checked>Style <input name="radio1" type="radio" value="barcode">Barcode <input type="button" value="check" onclick="checkme()"> </body> </html>34、脚本永不出错<script language="JavaScript"> function killErrors() { return true; } window.onerror = killErrors; </script>35、ENTER键可以让光标移到下一个输入框 <input onkeydown="if(event.keyCode==13)event.keyCode=9">36、各种样式的光标 auto :标准光标 default :标准箭头 hand :手形光标 wait :等待光标 text :I形光标 vertical-text :水平I形光标 no-drop :不可拖动光标 not-allowed :无效光标 help :?帮助光标 all-scroll :三角方向标 move :移动标 crosshair :十字标 e-resize n-resize nw-resize w-resize s-resize se-resize sw-resize37、页面进入和退出的特效 进入页面<meta http-equiv="Page-Enter" content="revealTrans(duration=x, transition=y)"> 推出页面<meta http-equiv="Page-Exit" content="revealTrans(duration=x, transition=y)"> 这个是页面被载入和调出时的一些特效。duration表示特效的持续时间,以秒为单位。transition表示使用哪种特效,取值为1-23: 0 矩形缩小 1 矩形扩大 2 圆形缩小 3 圆形扩大 4 下到上刷新 5 上到下刷新 6 左到右刷新 7 右到左刷新 8 竖百叶窗 9 横百叶窗 10 错位横百叶窗 11 错位竖百叶窗 12 点扩散 13 左右到中间刷新 14 中间到左右刷新 15 中间到上下 16 上下到中间 17 右下到左上 18 右上到左下 19 左上到右下 20 左下到右上 21 横条 22 竖条 23 以上22种随机选择一种38、在规定时间内跳转<meta http-equiv=V="REFRESH" content="5;URL=http://www.williamlong.info">39、网页是否被检索 <meta name="ROBOTS" content="属性值"> 其中属性值有以下一些: 属性值为"all": 文件将被检索,且页上链接可被查询; 属性值为"none": 文件不被检索,而且不查询页上的链接; 属性值为"index": 文件将被检索; 属性值为"follow": 查询页上的链接; 属性值为"noindex": 文件不检索,但可被查询链接; 属性值为"nofollow": 文件不被检索,但可查询页上的链接。 最大化窗口?<script language="JavaScript"> self.moveTo(0,0) self.resizeTo(screen.availWidth,screen.availHeight) </script>页面自动刷新(说明)当你做网页时,是不是有的时候想让你的网页自动不停刷新,或者过一段时间自动跳转到另外一个你自己设定的页面?其实实现这个效果非常地简单,而且这个效果甚至不能称之为特效。你只要把如下代码加入你的网页中就可以了。1,页面自动刷新把如下代码加入<head>区域中<meta http-equiv="refresh" content="20">,其中20指每隔20秒刷新一次页面.<meta http-equiv="refresh" content="20">2,页面自动跳转把如下代码加入<head>区域中<meta http-equiv="refresh" content="20;url=https://www.baidu.com">,其中20是指隔20秒后跳转到 https://www.baidu.com页面。<meta http-equiv="refresh" content="20;url=https://www.baidu.com">3、页面自动关闭5000是指5秒后弹出窗口自动关闭<body onLoad="setTimeout(window.close, 5000)">
2022年09月18日
32 阅读
0 评论
0 点赞
2022-08-06
xftp6 提示要继续使用此程序,要将应用更新为最新版本
序:xftp6 要继续使用此程序,您必须应用最新的更新或使用最新版本解决方法:1、电脑需要安装有 sublime、notepad++(已安装HEX-Editor插件)等能读写十六进制的编辑器;2、打开 xftp6 所安装的目录,右键 xftp6 快捷方式,选择打开文件所在位置,在目录下找到文件 nslicense.dll;3、Ctrl + F,查找 7F0C 81F9 8033 E101 ,将紧随其后的 0F86,改为0F83,保存文件,有时需要管理员身份运行编辑器去覆盖并保存修改文件,如下;xxxx xxxx xxxx xxxx 7F0C 81F9 8033 E101 0F86 改为 xxxx xxxx xxxx xxxx 7F0C 81F9 8033 E101 0F83
2022年08月06日
41 阅读
0 评论
0 点赞
1
2
...
7