首页 新闻 会员 周边

h5 canvas局部刷新

0
悬赏园豆:120 [已解决问题] 解决于 2017-08-02 09:23

   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)

学问生的主页 学问生 | 初学一级 | 园豆:52
提问于:2017-07-26 22:27
< >
分享
最佳答案
0
<!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是不能局部刷新的

看下能不能解决你的问题

收获园豆:120
旋律键盘 | 菜鸟二级 |园豆:324 | 2017-07-27 18:58

  首先感谢你的回复!我要实现的是自适应任何屏幕的全浏览器的canvas,canvas是元素不能刷新,我希望能有什么算法或者方法可以来解决这个问题。

学问生 | 园豆:52 (初学一级) | 2017-07-28 09:22

@学问生: canvas没有刷新的概念,只可以清除画布重新画,也就是帧的概念

比如第一帧某对象在坐标100,100

第二帧该对象在坐标105,105就实现移动了

其中第二帧渲染之前是要把整个画布清除的

清除画布的方法context.clearRect(x, y, width, height)

假如画布上有很多对象,清除以后全部都要重新画

感觉你问的不是很清楚,是不是这个意思

比如gif图片、电影,都是后面一张完全的帧替代了前面的帧,并不是里面某个对象刷新、移动了

这个和html的移动原理是不一样的,html、svg可以控制某个对象的动作,canvas是不可以的

旋律键盘 | 园豆:324 (菜鸟二级) | 2017-07-28 09:37

@旋律键盘: 一开始我认为是这样的,但是你看你的代码有用到清除吗,没有吧,没有清除怎么会引起重绘,没有save()也没有restore(),也没有put/getImageData(),在平板上画线速度被什么影响了我想知道,你们怎么看

学问生 | 园豆:52 (初学一级) | 2017-07-28 12:07

@学问生: 是因为没有优化,所以影响了性能。下面的代码优化了一下,你再测试一下行不行

<!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>

 

旋律键盘 | 园豆:324 (菜鸟二级) | 2017-07-28 18:17

@旋律键盘: 程序有问题,平板上画不了

学问生 | 园豆:52 (初学一级) | 2017-07-31 10:16

@学问生: 我这里android4.4和ios8.1测试都可以,你那里报什么错?

旋律键盘 | 园豆:324 (菜鸟二级) | 2017-07-31 18:47

@旋律键盘: 没有平板调试环境,不知道什么原因,我只是用平板访问在电脑上的服务器来查看的,画线没反应,手机上可以。

学问生 | 园豆:52 (初学一级) | 2017-08-01 11:21

@学问生: 平板系统版本和分辨率是多少?还有浏览器版本

旋律键盘 | 园豆:324 (菜鸟二级) | 2017-08-01 11:24

@旋律键盘: 是浏览器兼容性问题,搜狗可以,是哪个地方代码的问题,不能做兼容处理吗,requestAnimationFrame还是touches....

学问生 | 园豆:52 (初学一级) | 2017-08-01 17:38

@学问生: requestAnimationFrame可以写成webkitRequestAnimationFrame,changedTouches可以换成touches试试,其他的几乎没动,如果requestAnimationFrame不能用的话可以用setTimeout替代,搜狗上测试的结果有没有变快点?

旋律键盘 | 园豆:324 (菜鸟二级) | 2017-08-01 17:44
其他回答(1)
0

设定脏区域,清除再绘制,就是局部刷新

三国灰鼠 | 园豆:251 (菜鸟二级) | 2017-08-01 11:53

有这种方法吗?请贴出demo来看看,多谢

支持(0) 反对(0) 学问生 | 园豆:52 (初学一级) | 2017-08-01 16:07
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册