H5新特性
软件并不能实时定位,需要硬件支撑。
M端使用GPS;PC使用IP地址:精度低;IP经常会变,需要一个IP库(网上搜有,如ip.taobao.com)
window.navigator.geolocation
只问一次 单次:getCurrentPosition(成功,失败,参数) 获取当前位置 监听:watchPosition(成功,失败,参数)
在Ghrome浏览器上,它会向Google发出请求获取结果,通常情况下会失败;
结果:
<video>
<object type ="" params="">
</object> //flash
</video>
w = 600
H = 400
if(w/h>W/H){ //偏宽
//让宽度适应容器宽度
h = H*w/W
w = w
} else {
h = H
w = W*h/H
}
主机 > 程序 > 进程 > 线程 > 纤程
每个Web Workers都有自己的全局运行环境,其功能只是Javascript特性的一个子集。Worker运行环境由如下部分组成:
navigator对象
,只包括四个属性
:appName、appVersion、user Agent 、platform
location对象
,与window.location相同,不过其所有属性是只读的
self
对象,指向全局worker
对象importScripts()
方法,加载Worker所用到的外部Javascript文件Object、Array、Date
等XMLHTTPRequest
构造器setTimeout()和setInterval()
方法close()
方法,能立刻停止Worker运行//1、创建子进程
let w = new Worker('w1.js');//不能跨域
//2 发送
w.postMessage({});
//w1.js
//3、接收
//4、处理任务
//5、返回
//6、接收结果
我们知道,js是单线程运行的,这个特点可能会造成当某个操作特别耗时的时候,页面出现崩溃或无响应的状态。
Web Workers 能够赋予js多线程的能力,实质上是开启一个Web Workers线程,用于处理这些耗时的计算。
下面,通过一个示例说明——计算斐波那契数列:
知识:斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368…这个数列从第3项开始,每一项都等于前两项之和。 在数学上,斐波纳契数列以如下被以递推的方法定义: F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)
下面,我们通过Web Workers 计算它。 我们将线程分为UI线程和Web Workers线程:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=
, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>web workers</title>
</head>
<body>
<div class="calc">
<input type="text" id="text" />
<input type="button" value="获取结果" id="btnCal"/>
</div>
<p>结果:</p>
<p class="result" id="result"></p>
<script>
//UI 线程,用以处理DOM操作
var input = document.getElementById("text"),
cal = document.getElementById("btnCal"),
result = document.getElementById("result");
var getResult = function(){
var initVal = input.value;
var w = new Worker("./worker.js"); //创建web worker线程
w.postMessage(initVal); //向web worker 发送消息
w.addEventListener("message",function(event){ //接收Web workers 线程传回的消息
result.innerHTML = result.innerHTML + initVal + "斐波那契数列:"+event.data ;
},false)
}
cal.addEventListener("click",getResult,false);
</script>
</body>
</html>
web workers线程 worker.js
//web workers线程 ,用以处理耗时计算操作
function fibonacci(n){
return n<2 ? n : fibonacci(n-1) + fibonacci(n-2);
}
this.addEventListener("message",function(event){ //接收UI线程传递过来的消息
var resultVal = fibonacci(event.data);//计算对应的值
this.postMessage(resultVal); //将计算结果发送给UI线程
})
从上述,我们知道,Web Workers适合处理纯数据,或者与浏览器UI无关的长时间运行脚本。
我们在来看一个例子:用Web Workers 处理大的JSON字符串:
假设这个JSON字符串的数据量足够大,至少需要500ms才能解析完成,至于干扰了用户体验。
var worker = new Worker("jsonparse.js");
//数据就位时,调用事件处理器
worker.onmessage = function(event) {
var jsonData = event.data;//JSON结构
evaluateDate(jsonData);//使用JSON结构
}
worker.postMessage(jsonText);//传入要解析的大段JSON字符串
//当JSON数据存在时,该事件处理器会被调用
self.onmessage = function(event) {
//JSON字符串由event.data传入
var jsonText = event.data;
//解析JSON字符串
var jsonData = JSON.parse(jsonText);
//回传解析结果
self.postMessage(jsonData);
}
<div id="div1">将文件拖拽至此区域</div>
window.onload = function(){
let oDiv = document.getElementById('div1');
//ondragenter 进入
//ondragleave 离开
//ondragover 悬停
//ondrop 松开鼠标,如果dragover 不阻止默认事件,drop事件不会发生
oDiv.addEventListener('dragenter',function() {
oDiv.innerHTML = '释放鼠标';
},false);
oDiv.addEventListener('dragleave',function() {
oDiv.innerHTML = '将文件拖放至此区域';
},false);
oDiv.addEventListener('dragover',function(e) {
e.preventDefault(); //阻止默认事件
},false);
oDiv.addEventListener('drop',function(e) {
console.log(e.dataTransfer.files)
e.preventDefault();
},false);
}
富文本编辑器
let reader = new FileReader();
<canvas id="c1" width="100" height="100">
浏览器不支持canvas
</canvas>
window.onload = function(){
let oC = document.getElementById('c1');
let gd = oC.getContext('2d');//获取图形上下文,绘图用的接口(环境)
//路径操作---**与PS中的选区一样,框定一个操作的范围**
gd.moveTo(100,100);
gd.lineTo(300,200);
gd.lineTo(130,350);
gd.closePath(); //封口、闭合
//描边
gd.stroke();
}
画之前先清除之前所有的路径
gd.beginPath();
<canvas id="c1" width="100" height="100">
浏览器不支持canvas
</canvas>
window.onload = function(){
let oC = document.getElementById('c1');
let gd = oC.getContext('2d');
let lastX,lastY;
oC.onmousedown = function(ev){
lastX = ev.offsetX; //当前位置
lsstY = ev.offsetY;
oC.onmousemove = functioin(ev) {
gd.beginPath();
gd.moveTo(lastX,lastY);
gd.lineTo(ev.offsetX,ev.offsetY);
lastX=ev.offsetX; //前一次位置
lastY=ev.offsetY;
gd.stoke();
},
oC.onmouseup = function() {
oC.onmousemove = null;
oC.onmouseup = null;
}
}
}
function pie(startAng,endAng,color){
gd.beginPath();
let data= [100,300,200,150];
let colors = ['#000','#ccc','red','yellow']
let sum = data.reduce((tmp,item,index)=>tmp+item);
let angs = data.map(item=>360*item/sum);
let last = 0;
angs.forEach(ang=>{
pie(last,last+ang,colors[index]);
last+=ang;
})
}
如何让图形动起来(联系gif动画,帧)
1、canvas里的图形,只要画完了,就不能修改,因为canvas不会保存任何的图形信息; 2、gd.clearRect(x,y,w,h) 擦除一块区域,一般擦去整个画布:
gd.clearRect(0,0,oC.width,oCheight)
如何给图形增加事件
1、canvas本身没有事件 2、canvas中的事件操作要自己定义;
let 1=50,t=50,w=100,h=70;
gd.strokeRect(l,t,w,h);
oC.onclick = function(ev){//确定鼠标点击在区域内
if(ev.offsetX>=1 && ev.offsetX<=l+w
&&ev.offsetY>=t && ev.offsetY<=t+h){
}else {}
}
//计算点至圆心的距离
oC.mousemove = function(ev){
let a = ev.offsetX - cx; //横向距离
let b = ev.offsetY - cy; //纵向距离
let dis = Math.sqrt(a*a+b*b); //实际距离,利用勾股定理
gd.beginPath();
gd.arc(cx,cy,r,0,2*Math.PI,true);
if(dis<=r){ //距离小于半径
gd.fillStyle = 'yellow';
}else {//距离大于半径
gd.fillStyle = '#ccc';
}
gd.fill();
}
碰撞检测:矩形、圆形
高维检测
canvas变换 rotate translate scale
使用变换之前,先save()后restore()
function d2a(n){
return n*Math.PI/180;
}
function a2d(n){
return n*180/Math.PI;
}
window.onload = function(){
let oC = document.getElementById('c1');
let gd = oC.getContext('2d');
let rotate = 0;
gd.strokeRect(100,100,300,200);
setInterval(function(){
gd.clearRect(0,0,oC.width,oC.height);
rotate++;
gd.save(); //保存当前canvas的状态,如颜色、线宽、旋转、translate,但不包括图形本身
gd.translate(250,200); //先translate再rotate
gd.rotate(d2a(30)); //旋转单位:弧度;旋转以画布左上角为中心点旋转,而不是图形的中心
gd.strokeRect(-150,-100,300,200);
gd.restore();//恢复状态
},16);
}
<canvas id="c1" width="800" height="600"></canvas>
window.onload = function(){
let oC = document.getElementById('c1');
let gd = oC.getContext('2d');
let oImg = new Image();
oImg.src = 'logo.png';
oImg.onload = function() {//需要等到img加载完成才能drawImage
gd.clearRect(0,0,oC.width,oC.height);
//1、简易版 3个参数
//drawImage(img,x,y); //img要是真正的图片
gd.drawImage(oImg,0,0);
//2、完整版 9个参数,**适合做帧动画**
/*drawImage(
img,
sx,sy,sw,sh, s-source 源 :从哪取
dx,dy,dw,dh d-desitination 目标 :放到哪
)
gd.drawImage(
oImg,
50,50,32,32,
200,200,32,32
)
*/
}
}
window.onload = function(){
let oC = document.getElementById('c1');
let gd = oC.getContext('2d');
let oImg = new Image();
oImg.src= '1.jpg';
oImg.onload = function(){
gd.drawImage(oImg,0,0);
//获取一块像素区
let imageData = gd.getImageData(0,0,oC.width,oC.height);
//一个数组,每个像素的信息 imageData.data
alert(
r: ${imageData.data[0]}\n
g: ${imageData.data[1]}\n
b: ${imageData.data[2]}\n
a: ${imageData.data[3]}\n
)
//**操作像素点的颜色**
for(let r=0;r<oC.height;r++){
for(let c=0;c<oC.width;c++){
let avg = (imageData.data[(r*oC.width+c)*4]+imageData.data[(r*oC.width+c)*4+1]+imageData.data[(r*oC.width+c)*4+2])/3;
imageData.data[(r*oC.width+c)*4]+imageData.data[(r*oC.width+c)*4+1]+imageData.data[(r*oC.width+c)*4+2] = avg;
}
}
gd.putImageData(imageData,0,0);
}
}
若有800列 W)600行(H)的数组像素,要获取r行c列:
arr[(r*800+c)*4]
arr[(r*W+c)*4]