博客

three.js性能优化-(持续更新)

本文持续更新~~~

three.js是JavaScript编写的WebGL第三方库。提供了非常多的3D显示功能。在使用的时候,虽然three.js 做了优化,但是在使用不恰当的代码,也会产生性能损耗。帧率越低,给人感觉就越卡。这是我在开发中自己百度总结的,有不对的可以联系我啊

2019-08-22更新———————

1、disppose()方法得重要性
每当你创建一个three.js中的实例时,都会分配一定数量的内存。当你场景中几何体(geometry,bufferGeometry),材质(material),纹理(texture),渲染目标(WebFLRenderTarget)或者其他杂项废弃不用时,这时这些对象在你得代码里已经结束了他们得生命周期,但是three.js系统并不会帮你回收对象,他们依然存在于你的内存中,你需要手动使用dispose(),去主动释放这些资源。

  geometry.dispose();
  material.dispose();
  RenderTarget.dispose();
  texture.dispose();

对于纹理的内部资源仅在图像完全被加载后才会分配。如果你在图像被加载之前废置纹理,什么都不会发生。 没有资源被分配,因此也没有必要进行清理。

2、查看渲染场景信息
WebGLRenderer.info —— 渲染器中的一个特殊属性,具有一系列关于显存和渲染过程的统计信息。 除此之外,它还告诉你有多少纹理、几何体和着色器程序在内部存储。 如果你在你的应用程序中注意到了性能问题,一个较好的方法便是调试该属性,以便轻松识别内存泄漏。

console.log(“this.renderer.info”,this.renderer.info)

2019-08-08更新————-

1、矩阵变换优化
Matrix transformations

这是官网给出的建议,也就是说,当你需要去更新你场景中对象矩阵的时候,会涉及到计算,如果只是静态对象,并且操作不频繁,你可以关闭matrixAutoUpdate参数,手动去更新矩阵

Matrix transformations

但是当你采用第二种方式,去手动更新对象的矩阵,就需要关闭matrixAutoUpdate参数了

2018-08-06———-

1、预加载
在加载页面之前可以给个加载页面的缓冲,因为场景模型没有加载的时候会黑屏,加载一瞬间可能会出现闪屏等性能问题,十分影响用户体验的。

2、能用BufferGeometry代替Geometry的尽量用BufferGeometry
BufferGeometry 会缓存网格模型,性能要高效点。网格模型生成原理

1、Geometry 生成的模型是这样的 (代码)-> (CUP 进行数据处理,转化成虚拟3D数据) -> (GPU 进行数据组装,转化成像素点,准备渲染) -> 显示器
第二次操作时重复走这些流程。

2、BufferGeometry 生成模型流程 (代码) -> (CUP 进行数据处理,转化成虚拟3D数据) -> (GPU 进行数据组装,转化成像素点,准备渲染) -> (丢入缓存区) -> 显示器
第二次修改时,通过API直接修改缓存区数据,流程就变成了这样
(代码) -> (CUP 进行数据处理,转化成虚拟3D数据) -> (修改缓存区数据) -> 显示器

节约了GPU性能的运算性能。

3、少在requestAnimationFrame()动画下面执行操作
因为requestAnimationFrame()每秒执行60次,你要是在里面加个for循环,你的代码就炸了。还要减少浮点计算,系统对浮点计算开支比较大,尽量写成小数乘法。

4、学会使用clone()方法
var box=new THREE.BoxGeometry(10,10,10);//创建一个立方体几何对象
var box2 = box.clone();//克隆几何体
box2.scale.set(2,2,2);//通过缩放调整大小
clone()返回一个新的几何体对象,返回新的几何体对象包含原来的几何体顶点数据、顶点索引数据、UV坐标数据。就不用重新创建相同的对象,浪费时间,具体详细可以看这篇文章

5、纹理图片尺寸一定得是2的幂次方,并尽可能的小
使用 new THREE.TextureLoader().load( “water.jpg” )加载纹理贴图时,如果不是2的幂次方,那么three.js就会自动转为最合适的2的幂次方尺寸,并在控制台打印出黄色警告。这个不是three.js设置的,是webgl限制的,是为了适合Mipmap(为了加快渲染速度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件)设置。

图片尽可能的小,合并,图片越大不代表越清晰,也会和纹理过滤等各属性有关。降低图片大小,减少内存占用。

6、跳帧设置
// limit framerate to save battery, solution by mrdoob (author of three.js)
// https://stackoverflow.com/questions/11285065/limiting-framerate-in-three-js-to-increase-performance-requestanimationframe
setTimeout(() => {
requestAnimationFrame(this.animateScene);
}, 30);
这样每到skip的时候跳过一次渲染执行,以减少渲染次数,在保证不影响用户体验的情况下,尽可能的多跳帧。

7、对粒子群进行转换,而不是每个粒子
使用THREE.Sprite时,可以更好地控制单个粒子,但是当使用大量的粒子的时候,这个方法的性能会降低,并且会更复杂。此时可以使用THREE.SpriteCloud,可以轻松地管理大量的粒子,进行整体操作,此时对单个粒子的控制能力会减弱。

8、模型的面越少越好,模型过于细致会增加渲染开销
three场景导入模型时,可以在保证最低清晰度的时候,降低模型的复杂度,面越多,模型越大,加载所需开销就越大

9、性能检测插件(stats.js)
使用该插件进行检测帧率,网上有很多使用教程,可以自己百度

three.js stats

10、使用chrome的插件three.js inspector,可以在控制台调试查看场景中的各个模型等
但是你需要将你的场景对象暴漏出来给window,这个插件才可以读取到你的场景信息

this.scene = new THREE.Scene();
window.scene=this.scene

three.js inspector

欢迎转载,转载需带着文章出处链接~~

微信小程序实现长按拖动排序

前端对接海康威视监控

  1. vue对接官方插件WebControl:https://blog.csdn.net/qq_41732963/article/details/115670910
  2. vue无海康官方插件对接:https://blog.csdn.net/qq_41732963/article/details/115655739
  3. 海康监控流有多种协议
  • 实时串流协议(Real Time Streaming Protocol,RTSP)是一种网络应用协议,专为娱乐和通信系统的使用,以控制流媒体 服务器。该协议用于建立和控制终端之间的媒体会话。媒体服务器的客户端发布VCR命令,例如播放,录制和暂停,以便于实时控制从服务器到客户端(视频点播)或从客户端到服务器(语音录音)的媒体流。
  • RTMP 实时消息协议(英语:Real-Time Messaging Protocol,缩写RTMP)也称实时消息传输协议,是最初由Macromedia为通过互联网在Flash播放器与一个服务器之间传输流媒体音频、视频和数据而开发的一个专有协议。
  • HLS HTTP Live Streaming(缩写是HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议

总结,因为RTMP需要依赖Flash,但是现在很多浏览器需要自己主动安装插件,所以给到客户使用是不太合理的,所以建议采用HLS协议

我这里使用的取流方式是HLS所以返回的URL后缀的m3u8,这种格式的文件不能直接播放。

hls示例(直接运行就可以):

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="UTF-8">
		<title>播放m3u8格式</title>
		<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
		<script src="https://unpkg.com/video.js/dist/video.js"></script>

	</head>
	<body>
		<style>
			.video-js .vjs-tech {position: relative !important;}
    	</style>
		<div>
			<video id="myVideo" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" data-setup='{}'
			 style='width: 100%;height: auto'>
				<source id="source" src="http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8" type="application/x-mpegURL">
				</source>
			</video>
		</div>
	</body>

	<script>
		var myVideo = videojs('myVideo', {
			bigPlayButton: true,
			textTrackDisplay: false,
			posterImage: false,
			errorDisplay: false,
		},function ready(){
			this.play()
		})
		// myVideo.play()
		var changeVideo = function(vdoSrc) {
			if (/\.m3u8$/.test(vdoSrc)) {
				myVideo.src({
					src: vdoSrc,
					type: 'application/x-mpegURL'
				})
			} else {
				myVideo.src(vdoSrc)
			}
			myVideo.load();
			myVideo.play();
		}
	</script>

RTMP协议播放(这个chrome需要安装Flash插件,或者直接用360浏览器打开,他好像集成了Flash插件)

<!DOCTYPE html>
<html>
    <head>
        <title>播放器</title>
        <!-- 导入的videojs是7.0版本以上的,集成VHS协议库,可播放HLS流媒体视频 -->
        <link href="videolib/css/video-js.min.css" rel="stylesheet" type="text/css">
        <script src="videolib/js/video.min.js"></script>
        <!-- 引入的videojs-flash.js插件主要是为播放rtmp视频流-->
        <script src="videolib/videojs-flash.min.js"></script>
    </head>
    <body>
        <video id='myvideo' width=960 height=540 class="video-js vjs-default-skin" controls>
            <!-- RTMP直播源地址-->
            <source src="rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp"> 
        </video>
        <script> 
            var player = videojs('myvideo', {}, function(){console.log('videojs播放器初始化成功')})
            player.play();
        </script>
    </body>
</html>

示例代码,github下载

前端读取apk包的版本号信息

需求:后端需要上传apk的包,给到后台,远程更新apk版本,所以需要上传并读取apk的版本名和版本号

配置:vue2 + ant-design-vue

代码:

上传没啥好说的,调用的是ant-design-vue框架的上传模块,主要关注的是上传后,远程更新的时候需要读取的apk版本信息。

  1. 安装 app-info-parser插件
npm install app-info-parser

2. 上传文件,拿到file对象

3. 导入插件,读取apk版本信息

      const AppInfoParser = require('app-info-parser')
      const parser = new AppInfoParser(this.formData.get('file'))
      parser.parse().then(result => {
        let params={
          apkVersionCode: result.versionCode, 
          apkVersionName: result.versionName,
        }
        //处理后续逻辑
      })

结束~

mac终端下SVN和Git命令行操作

整理供自己使用

一、svn常规命令行

参考文章

1、将文件checkout到本地目录

1 svn checkout path(path是服务器上的目录)
2 例如:svn checkout svn://192.168.1.1/pro/domain
3 简写:svn co

2、往版本库中添加新的文件

1 svn add file
2 例如:svn add test.php(添加test.php)
3 svn add *.php(添加当前目录下所有的php文件)
4 svn add home/*(添加指定目录下的所有文件)

3、将改动的文件提交到版本库

1 svn commit -m “LogMessage“ [-N] [--no-unlock] PATH        (如果选择了保持锁,就使用–no-unlock开关)
2 例如:
  svn commit -m “add test file for my test“ test.php
3 简写:
  svn ci

4、加锁/解锁

1 svn lock -m “LockMessage“ [--force] PATH
2 例如:svn lock -m “lock test file“ test.php
3 svn unlock PATH

5、更新到某个版本

1 svn update -r m path
2 例如:
3 svn update如果后面没有目录,默认将当前目录以及子目录下的所有文件都更新到最新版本。
4 svn update -r 200 test.php(将版本库中的文件test.php还原到版本200)
5 svn update test.php(更新,于版本库同步。如果在提交的时候提示过期的话,是因为冲突,需要先update,修改文件,然后清除svn resolved,最后再提交commit)
6 简写:svn up

6、查看文件或者目录状态

1 1)svn status path(目录下的文件和子目录的状态,正常状态不显示)
2 【?:不在svn的控制中;M:内容被修改;C:发生冲突;A:预定加入到版本库;K:被锁定】
3 2)svn status -v path(显示文件和子目录状态)
4 第一列保持相同,第二列显示工作版本号,第三和第四列显示最后一次修改的版本号和修改人。
5 注:svn status、svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的,原因是svn在本地的.svn中保留了本地版本的原始拷贝。
6 简写:svn st

7、删除文件

1 svn delete path -m “delete test fle“
2 例如:svn delete svn://192.168.1.1/pro/domain/test.php -m “delete test file”
3 或者直接svn delete test.php 然后再svn ci -m ‘delete test file‘,推荐使用这种
4 简写:svn (del, remove, rm)

8、查看日志

1 svn log path
2 例如:svn log test.php 显示这个文件的所有修改记录,及其版本号的变化

9、查看文件详细信息

1 svn info path
2 例如:svn info test.php

10、比较差异

1 svn diff path(将修改的文件与基础版本比较)
2 例如:svn diff test.php
3 svn diff -r m:n path(对版本m和版本n比较差异)
4 例如:svn diff -r 200:201 test.php
5 简写:svn di

11、将两个版本之间的差异合并到当前文件

1 svn merge -r m:n path
2 例如:svn merge -r 200:205 test.php(将版本200与205之间的差异合并到当前文件,但是一般都会产生冲突,需要处理一下)

12、SVN 帮助

1 svn help
2 svn help ci

13、版本库下的文件和目录列表

1 svn list path
2 显示path目录下的所有属于版本库的文件和目录
3 简写:svn ls

14、创建纳入版本控制下的新目录

1 svn mkdir: 创建纳入版本控制下的新目录。
2 用法: 1、mkdir PATH…
       2、mkdir URL…
3 创建版本控制的目录。
  1、每一个以工作副本 PATH 指定的目录,都会创建在本地端,并且加入新增调度,以待下一次的提交。
  2、每个以URL指定的目录,都会透过立即提交于仓库中创建。
4 在这两个情况下,所有的中间目录都必须事先存在

15、恢复本地修改

1 svn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。revert:
2 用法: revert PATH…
3 注意: 本子命令不会存取网络,并且会解除冲突的状况。但是它不会恢复
4 被删除的目录

16、代码库URL变更

 1 svn switch (sw): 更新工作副本至不同的URL。
 2 用法: 1、switch URL [PATH]
 3 2、switch –relocate FROM TO [PATH...]
 4  
 5 1、更新你的工作副本,映射到一个新的URL,其行为跟“svn update”很像,也会将
 6 服务器上文件与本地文件合并。这是将工作副本对应到同一仓库中某个分支或者标记的
 7 方法。
 8 2、改写工作副本的URL元数据,以反映单纯的URL上的改变。当仓库的根URL变动
 9 (比如方案名或是主机名称变动),但是工作副本仍旧对映到同一仓库的同一目录时使用
10 这个命令更新工作副本与仓库的对应关系。

17、解决冲突

1 svn resolved: 移除工作副本的目录或文件的“冲突”状态。
2 用法: resolved PATH…
3 注意: 本子命令不会依语法来解决冲突或是移除冲突标记;它只是移除冲突的
4 相关文件,然后让 PATH 可以再次提交。

18、分支处理

创建分支:svn copy  svn://xx.com/branch -m 'make branches trunk'
切换分支:svn switch svn://xx.com/branch(切换回来:svn switch svn://xx.com/trunk)
合并分支到主干:svn switch svn://xx.com/trunk
               svn merge svn://xx.com/branch

二、 提交错误记录

1、 Skipped ‘src/views/page.vue’ — Node remains in conflict

svn文件冲突处理,在svn创建的目录(一般为网站根目录)执行语句,***.php为skipped 后面的文件路径,复制替换为自己的

svn revert --depth=infinity src/views/page.vue

svn update

三 、Git常规命令行

送给新手的简单命令操作、远程Git和local的同步实现流程:

1、把git上的代码clone到本地

$ git clone http:xxxx(地址,可以http也可以ssh)

2、clone到本地以后、使用branch -a 查看远程所有分支

$  git branch -a

3、如若你有分支:master branch1 branch2 ,使用checkout用来切换分支。还可以用第2条指令去创建本地分支目录和远程的保持一致,并且切换远程分支到本地分支目录

$ git checkout branch1

$ git checkout -b branch1 origin/branch1

4、在本地修改完代码后、添加项目到缓存区

$ git add xx.html

也可添加某个文件下的所有文件

$ git add xx/

如果想提交所有的文件就git add *
5、保存完成后可以提交到本地

$ git commit -m '提交说明'

6、最后提交git服务器,要加上分支的名字,默认master目录不加。

$ git push origin branch

错误合集:
7、如果提交代码提示报错error: failed to push some refs to ‘https://xxxxxx.com/charge/monitors.git’,则是因为本地仓库与线上仓库代码不一致,经常会因为reademe文件等不同步导致的,需要先进行代码合并

$ git pull –rebase origin master

再提交代码

$ git push -u origin master

就完成了

字符串中找最大值-一个面试题引发的一个文章


题目:写一个函数,输入一段合法的字符数组(n<1024),请用JavaScript从字符数组中找出最大的数值,比如(asc23423v234),得到的最大数值是23423。注意:数值为常用数值表达方式。(建议不要用正则,基本是死路)
部分测试用例:
1)输入asc23423v234,输出23423
2)输入pppp12bbbbbb12.31cccc,输出31
3)输入54.4..6Ⅲ-44.4+++5-4,输出54.4

解题:

  function calcMaxNumber(str) {
    //转成数组
    let arr = str.split('');
    // 控制断字
    let bool = false;
    // 选取数字和.的正则
    let regexp = /[\d|.]/i;
    let filterArr = [];
    //把连续数字和带点的连续数字抽取成新的数组
    arr.reduce((resStr, value, index, arr) => {
      if (regexp.test(value)) {
        bool = true;
        if (index === arr.length - 1) {
          let str = resStr + value;
          return filterArr.push(str);
        }
        return resStr + value;
      } else {
        if (bool) {
          filterArr.push(resStr);
        }
        bool = false;
        return '';
      }
    }, '');
    // 对过滤的数组中带有.的项进行拆分
    filterArr = filterArr.map(num => {
      if (num.includes('.')) {
        return handlePointStr(num);
      } else {
        return num;
      }
    });
    //对有.的字符串 进行处理 例如‘21.23.34’ 返回 [21.23,23.34,34]
    function handlePointStr(str) {
      let arr = str.split('.');
      if (arr[arr.length - 1] == '') {
        arr.splice(arr.length - 1);
      }
      let newArr = [];
      for (i = 0; i < arr.length - 1; i++) {
        newArr.push(arr[i] + '.' + arr[i + 1]);
      }
      newArr.push(arr[arr.length - 1]);
      return newArr;
    }
    // 二维数组进行扁平化
    filterArr = filterArr.toString().split(',');
    return Math.max(...filterArr);
    console.table(filterArr);
  }
 let max = calcMaxNumber('54..4..6II44.4+++5-4');
 console.log(max);

js输入框字符宽度判断-已知字符串宽度/未知字符串宽度


一、需求说明
一串字符长度很好判断,this.text.length就拿到了,但是对于一个固定宽度的文本框,要求不能超过宽度,那么就要计算这行文本的宽度。汉字是等宽字符,但是数字和英文则宽度不一致,这里的建议是,以数字为单位,比如1,那么一行最多输入20的汉子,长度则为20,字母则要按照最宽的字符w去计算,数字则以5为单位去计算。

二、解决方案
情形一:已知的字符串宽度,根据要求截取固定宽度的字符串,比如我已经知道了一串字符串了,去截取固定的宽度
方法一:

String.prototype.visualLength = function(size,family)
      {
    var ruler = $(“#ruler”).css({
    ”font-size”:size || “inherit”,
  ”font-family”:family || “inherit”
     });
  ruler.text(this);
  return ruler.width();
      }

方法二:

var canvas = document.createElement(‘canvas’)//首先创建一个canvas标签
var ctx = canvas.getContext(“2d”) as CanvasRenderingContext2D;//把canvas的画笔给调出来
ctx.font=”26px 思源黑体”;//设置字体大小和字体,这一步很重要,直接影响了测量结果,因为14px和16px的字体的宽度是不一样的
var width = ctx.measureText(this.name).width;//开始测量字体的宽度
情形二:未知字符串的宽度,根据动态输入的字符判断当前的宽度,根据输入框宽度截取能显示的最多字符长度,比如一个输入框固定了长度,每输入一个字符后则判断是否超过,超过后就截去超过的部分
按照比例,汉字宽度为1,则英文为0.89,数字为0.57,符号(比如=?)

    @Watch('backText')
    sendText(){
      let count=0;
      let maxLen:any
      for (let index = 0; index < this.backText.length; index++) {
        let value=this.backText[index];
        if (value.match(/[A-Z]/g) || value.match(/[\u4e00-\u9fa5]/g)) {//大写英文/中文
          count+=1;
        }else if (value.match(/[a-z]/g)) {//小写英文
          count+=0.62;
        }else if (value.match(/[0-9]/g)||value.match(/[%&',;=?~$\x22]/g)) {//数字/符号
          count+=0.54;
        }else if (value.match(/[(^\s*)|(\s*$)]/g)) {//空格
          count+=0.2;
        }
        if (count>19) {
          maxLen=index;
          this.backText=this.backText.substring(0,index);
          alert(`亲,内容已输满了哦~`;  
          return;
        }

      }
    }

欢迎转载,转载需带着文章出处链接~~

JavaScript前端实用小函数


1、判断是手机还是pc端

function IsPC() {
    var userAgentInfo = navigator.userAgent;
    var Agents = ["Android", "iPhone",
        "SymbianOS", "Windows Phone",
        "iPad", "iPod"
    ];
    var flag = true;
    for(var v = 0; v < Agents.length; v++) {
        if(userAgentInfo.indexOf(Agents[v]) > 0) {
            flag = false;
            break;
        }
    }
    return flag;
}

2、判断手机是横屏还是竖屏

var isPortrait = true; //竪屏
function onMatchMeidaChange() {
    var mql = window.matchMedia('(orientation: portrait)')
    if(mql.matches) {
        // 竖屏
        isPortrait = true;
    } else {
        //橫屏
        isPortrait = false;
    }
}
onMatchMeidaChange();
window.matchMedia('(orientation: portrait)').addListener(onMatchMeidaChange);

3、简单的防抖动函数

function debounce(func, wait, immediate) {
    // 定时器变量
    var timeout;
    return function() {
        // 每次触发 scroll handler 时先清除定时器
        clearTimeout(timeout);
        // 指定 xx ms 后触发真正想进行的操作 handler
        timeout = setTimeout(func, wait);
    };
};


// 采用了防抖动
var i=0;
window.addEventListener('scroll',debounce(function(){
    //功能代码
    console.log(i);
},500));

4、简单的节流函数

// 简单的节流函数
function throttle(func, wait, mustRun) {
    var timeout,
        startTime = new Date();

    return function() {
        var context = this,
            args = arguments,
            curTime = new Date();

        clearTimeout(timeout);
        // 如果达到了规定的触发时间间隔,触发 handler
        if(curTime - startTime >= mustRun){
            func.apply(context,args);
            startTime = curTime;
        // 没达到触发间隔,重新设定定时器
        }else{
            timeout = setTimeout(func, wait);
        }
    };
};


// 采用了节流函数
var i=0;
window.addEventListener('scroll',throttle(function(){
    //功能代码
    console.log(i);
},500,1000));

5、判断是手机QQ内置浏览器还是外部浏览器

function isQQ(){
    var ua = navigator.userAgent.toLowerCase();
    if (ua.match(/QQ/i) == "qq") {
            return true;
        }
}

6、判断是不是微信端

function isWeChat() {
    var ua = navigator.userAgent.toLowerCase();
    if(ua.match(/MicroMessenger/i) == 'micromessenger') {
	return true;  
     }
     return false
}

7、判断ie浏览器版本

function IEVersion() {
            var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串  
            var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器  
            if(isIE) {
                var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
                reIE.test(userAgent);
                var fIEVersion = parseFloat(RegExp["$1"]);
                if(fIEVersion >= 9) {
                    console.log("浏览器版本为IE9以上版本");
                } else {
                    console.log("浏览器版本为IE8以下版本");
                }
            }
        }

8、 浏览器刷新回到顶部

window.onbeforeunload = function() {
    document.documentElement.scrollTop = 0; //ie下
    document.body.scrollTop = 0; //非ie
}

9、 判断是安卓还是ios

function isAndroid(){
			var u = navigator.userAgent;
			var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
			var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
			return isAndroid
		}
function isiOS(){
			var u = navigator.userAgent;
			var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
			return isiOS 
		}

移动端最小字体设置失效问题


直接说总结:
移动端最小字体为12px(仅chrome有此限制),建议最小使用12px;
如果设计稿中有小于12px的字体,按实际字号写css样式,如果超出最小字体,可以用scale进行缩放展示;
iphone类移动设备不受最小字号限制;
其它设备可能会受8px限制;
说明:对于不同的手机和浏览器,支持的最小字体大小是不一样的,因此指定了小于手机的最小字体就会失效无法执行。需要注意的是,在html5文本中可能会更加明显,但是在svg中,由于svg是可以无损无限缩放,就会产生一个误区,以为只要缩放至指定的尺寸就会相应的放大就会适应手机,但其实只是整体缩放,其值并不会改变。

参考文章:https://www.cnblogs.com/he-lian/p/4512276.html

欢迎转载,转载需带着文章出处链接~~

微信jssdk 自定义分享ios问题总结


1 分享功能前提条件必须保证通过config接口注入权限验证配置成功
需要将必备的数据配置成功,并且需要将你用到的签名注入在jsApiList数据里

参考文章

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [
                "onMenuShareTimeline",
                "onMenuShareAppMessage",
                "onMenuShareQQ",
                "onMenuShareWeibo",
                "onMenuShareQZone"
    ] // 必填,需要使用的JS接口列表
});

2 调试模式报错:invalid signature 很明显签名错误
当wx.config的debug设为true的话打开页面会显示签名是否成功,若显示 invalid signature,则是签名报错,这时候你就需要去检查你的签名配置

解决办法
1、确认签名算法是否正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
2、确认config中noncestr, timestamp与用以签名中的对应noncestr, timestamp一致。
3、确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
4、确认url是页面完整的url,包括GET参数部分。
参考文章

3 微信分享非安全域名链接导致分享失败
微信后面做了调整,参考文章,链接域名或路径必须与当前页面对应的公众号JS安全域名一致,否则将调用失败

获取“分享到朋友圈”按钮点击状态及自定义分享内容接口

wx.onMenuShareTimeline({
    title: '', // 分享标题
    link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
    imgUrl: '', // 分享图标
    success: function () { 
        // 用户确认分享后执行的回调函数
    }
});

也就是说,你的link必须是和你的公众号js安全域名一致。例如,当前页面是 http://www.abc.com/123,其公众号对应的JS安全域名为 www.abc.com 以及 www.xyz.com,则分享自定义链接 http://www.abc.com/456 可以成功,分享 http://www.xyz.com/123 或 http://www.def.com/123 均将失败。

如果说你分享跳转页面必须是非安全域名下的链接,那你可以单独做一个转发页面,通过转发链接进入这个转发页面后,再直接跳转到拼接好的授权页面。参考代码:非安全链接分享解决办法

4 需要对公众号进行认证
公众号平台是有权限的,你要确保你的公众号已经获得了分享权限功能。因为微信暂不支持个人类型的公众帐号申请微信认证。所以此类公众号无需进行认证就有分享权限,企业号什么的就自行去认证吧。

参考文章

5分享link链接里面不要是拼接的地址,直接写成固定链接
比如 link对应参数比如:‘http://baidu/a/b/c/x/xx/x ’不要写成‘http://baidu/‘+ url+’/a/b/c/x/xx/x’

参考文章

6 link参数带中文或者特殊字符
带中文的url在安卓中应该也是会出问题的,但是安卓会自动encodeURIComponent(),而ios不会。所以会出现安卓自定义可以正常分享,但是ios就不行。

参考文章

7 微信官方取消了cancel回调
还有一点需要注意,就是微信为了杜绝一些商家的强制分享,取消了cancel回调函数,也就是说,只要用户点击了分享按钮,就会出发success回调

参考文章

欢迎转载,转载需带着文章出处链接~~

遇到问题在更新~~~~