h5 canvas局部刷新是怎么实现的,canvas实现的自由画线功能在平板上用手指画线时渲染比较慢?解决在平板上的canvas画线流畅性,不讨论手机上的。能真正解决问题的另发红包50以上。如果能解决安卓系统超大屏上跟原生APP应用上画线一样流畅,会再增加奖励。有兴趣的,知道的,了解过的,做过类似项目要求的,都欢迎大家给意见!
请帮忙扩散,共同进步
以下是我的原生js,超大屏上画线很慢,平板上速度一般
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var w=document.documentElement.clientWidth
var h=document.documentElement.clientHeight
canvas.setAttribute('width',w)
canvas.setAttribute('height',h-10)
var isDrawingMode,x,y,a,b;
var onMousedown=function(event){
ctx.beginPath()
isDrawingMode=true
//ctx.save()
if(event.type=='touchstart'){
var touch=event.touches[0]
return point={
x : Number(touch.pageX),
y : Number(touch.pageY)
}
}else{
return point={
x : event.pageX,
y : event.pageY
}
}
}
var cols=rows=[];
var onMousemove=function(){
//cols=rows=[]
if(isDrawingMode==true){
if(event.type=='touchmove'){
var touch=event.changedTouches[0]
a=Number(touch.pageX)
b=Number(touch.pageY)
}else{
a=event.pageX
b=event.pageY
cols.push(a)
rows.push(b)
}
//ctx.beginPath()
ctx.strokeStyle="purple"
ctx.lineWidth=3
ctx.moveTo(point.x,point.y)
ctx.lineTo(a,b)
ctx.stroke()
point.x=a
point.y=b
}
//ctx.restore()
}
var onMouseup=function(){
isDrawingMode=false
}
canvas.addEventListener('mousedown', onMousedown,false)
canvas.addEventListener('mousemove', onMousemove,false)
canvas.addEventListener('mouseup', onMouseup,false)
canvas.addEventListener('touchstart', onMousedown,false)
canvas.addEventListener('touchmove', onMousemove,false)
canvas.addEventListener('touchend', onMouseup,false)
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <style> html, body { margin: 0; padding: 0; height: 100%; width: 100%; } canvas { display: block; background-color: #eee; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; } </style> </head> <body> <canvas id="canvas"></canvas> <script> var canvas = document.getElementById('canvas'); canvas.width = 300; canvas.height = 200; // 画布太大会影响性能 // canvas.width = document.body.clientWidth; // canvas.height = document.body.clientHeight; var ctx = canvas.getContext('2d'); ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.lineWidth = 2; var x = 0; var y = 0; var md = false; addEventListener(canvas, ['mousedown', 'touchstart'], function(e) { var xy = getClientXY(e); x = xy.x; y = xy.y; md = true; ctx.beginPath(); }, false); addEventListener(canvas, ['mousemove', 'touchmove'], function(e) { if (!md) { return; } e.preventDefault(); var xy = getClientXY(e); ctx.moveTo(x, y); ctx.lineTo(xy.x, xy.y); ctx.stroke(); x = e.offsetX; y = e.offsetY; }, false); addEventListener(canvas, ['mouseup', 'touchend'], function(e) { md = false; ctx.closePath(); }, false); function getClientXY(e) { return e.clientX !== undefined ? { x: e.clientX, y: e.clientY } : { x: e.touches[0].clientX, y: e.touches[0].clientY, } } function addEventListener(ele, name, callback) { for (var i = 0; i < name.length; i++) { ele.addEventListener(name[i], callback); } } </script> </body> </html>
刚才写的
画布太大会影响性能,你可以逐步调下大小测试
canvas是不能局部刷新的
看下能不能解决你的问题
首先感谢你的回复!我要实现的是自适应任何屏幕的全浏览器的canvas,canvas是元素不能刷新,我希望能有什么算法或者方法可以来解决这个问题。
@学问生: canvas没有刷新的概念,只可以清除画布重新画,也就是帧的概念
比如第一帧某对象在坐标100,100
第二帧该对象在坐标105,105就实现移动了
其中第二帧渲染之前是要把整个画布清除的
清除画布的方法context.clearRect(x, y, width, height)
假如画布上有很多对象,清除以后全部都要重新画
感觉你问的不是很清楚,是不是这个意思
比如gif图片、电影,都是后面一张完全的帧替代了前面的帧,并不是里面某个对象刷新、移动了
这个和html的移动原理是不一样的,html、svg可以控制某个对象的动作,canvas是不可以的
@旋律键盘: 一开始我认为是这样的,但是你看你的代码有用到清除吗,没有吧,没有清除怎么会引起重绘,没有save()也没有restore(),也没有put/getImageData(),在平板上画线速度被什么影响了我想知道,你们怎么看
@学问生: 是因为没有优化,所以影响了性能。下面的代码优化了一下,你再测试一下行不行
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <style> html, body { margin: 0; padding: 0; height: 100%; width: 100%; } canvas { display: block; margin: auto; background-color: #eee; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; } </style> </head> <body> <canvas id="canvas"></canvas> <script> var canvas = document.getElementById('canvas'); canvas.width = document.body.clientWidth; canvas.height = document.body.clientHeight; var ctx = canvas.getContext('2d'); var points = []; var md = false; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.lineWidth = 1; // 渲染记录的点 requestAnimationFrame(render); canvas.addEventListener('touchstart', start, false); canvas.addEventListener('touchmove', move, false); canvas.addEventListener('touchend', end, false); canvas.addEventListener('mousedown', start, false); canvas.addEventListener('mousemove', move, false); canvas.addEventListener('mouseup', end, false); function start(e) { var p = getPoint(e); md = true; ctx.beginPath(); ctx.moveTo(p.x, p.y); } function move(e) { if (!md) { return; } e.preventDefault(); var p = getPoint(e); // 把所经过的点记录一下,集中渲染 points.push([p.x, p.y]); } function end(e) { md = false; } function render() { if (points.length) { for (var i = 0; i < points.length; i++) { ctx.lineTo(points[i][0], points[i][1]); } ctx.moveTo(points[i - 1][0], points[i - 1][1]); ctx.stroke(); points = []; if (!md) { ctx.closePath(); } } requestAnimationFrame(render); } function getPoint(e) { return e.pageX !== undefined ? { x: e.pageX - e.target.offsetLeft, y: e.pageY - e.target.offsetTop } : { x: e.changedTouches[0].pageX - e.target.offsetLeft, y: e.changedTouches[0].pageY - e.target.offsetTop, } } </script> </body> </html>
@旋律键盘: 程序有问题,平板上画不了
@学问生: 我这里android4.4和ios8.1测试都可以,你那里报什么错?
@旋律键盘: 没有平板调试环境,不知道什么原因,我只是用平板访问在电脑上的服务器来查看的,画线没反应,手机上可以。
@学问生: 平板系统版本和分辨率是多少?还有浏览器版本
@旋律键盘: 是浏览器兼容性问题,搜狗可以,是哪个地方代码的问题,不能做兼容处理吗,requestAnimationFrame还是touches....
@学问生: requestAnimationFrame可以写成webkitRequestAnimationFrame,changedTouches可以换成touches试试,其他的几乎没动,如果requestAnimationFrame不能用的话可以用setTimeout替代,搜狗上测试的结果有没有变快点?
设定脏区域,清除再绘制,就是局部刷新
有这种方法吗?请贴出demo来看看,多谢