canvas内移动图形原图不消失问题

问题出处

在初学html的canvas时,我们遇到了对图形的移动,放大,旋转的操作;会发现在使用translate();scale()和rotate()的时候,都只是再次绘画了一个图形,接下来我们以边框为例子,进行演示。
我们先建立骨架,和绘制一个边框

<body onload="drawrect()">		//预先加载绘制边框函数
    <div>
        <button onclick="moveX_rect(1)">上移</button><button onclick="moveX_rect(0)">下移</button>
    </div>
    <canvas id="mycanvas"  width="1700px" height="800px" style="background-color:gray; border:3px black solid;"
    onmousemove="getcnvsxy(event)" onmouseout="cleanxy()"></canvas>
    <script>
        function getbyid(id){		//定义通过id获取元素的函数
            return document.getElementById(id); 
        }
        function drawrect(){		//绘制边框函数
            var cnv=getbyid("mycanvas");
            var cxt=cnv.getContext("2d");
            cxt.lineWidth=5;		//边框线的宽度为5
            cxt.strokeStyle="black";		//边框线的颜色为黑
            cxt.strokeRect(200,100,100,100);	//从X为200px,Y为100px的位置绘制一个长100px宽100px的边框	
        }
        function moveX_rect(a){			//定义移动函数
            var cnv=getbyid("mycanvas");
            var cxt=cnv.getContext("2d"); 
            a?cxt.translate(0,-10):cxt.translate(0,10);		//onlick触发的是参数不同的同一个函数,用三目运算来决定是上移还是下移
            drawrect();		//调用绘制函数,再绘制一个移动后的函数
        }
        </script>
</body>

在以上代码执行后效果图:
首次执行
我们接下来进行三次上移观察效果:
三次上移后
四次下移后:
四次下移

我们会发现,每次上移,都会保留原先的边框,原因就是我们在移动的图形时,使用了drawrect()重新绘制了一个新边框,只不过是位置变了而已!那我们如何解决呢???

在课本《移动WEB开发实战》的一串代码中我得到了启发:

function spn1_click(){
	var cnv=$$("cnvMain");
	var cxt=cnv.getContext("2d");
	cxt.translate(-20,-20);
	drawRect();
	cxt.translate(40,40);
	drawRect();
}

这串代码的意思是想让我们发现,每次移动都是相对上一次而做出的改变,效果图就不展示了,口头赘述一下:第一次(-20,-20),我们的图形X轴-20,Y轴-20,整个图形往左上角移动;第二次(40,40),我们的图形X轴+40,Y轴+40,第一次移动后的图形,也就是在左上角的图形往右下角移动第一次的两倍距离;我觉得我是时候放张图了:
在这里插入图片描述


解决思路与方案!!!

既然一次可以绘制两个图形,咱就让一个图形覆盖住原先的图形!?

在上述书本提到的例子中,有两个drawrect()函数,我们可以把其中一个变成translate(0,0),让它先绘制的图形覆盖住原先的图形,既然要让原先的图形看不见,咱就是说,把先绘制的图形颜色设置成和背景颜色一样,这就看不见啦!!!

例如:在我给出的代码中,我们这样修改:
1.复制一份drawrect(),把名字改为drawrect1()
2.drawrect1()里面我们把颜色设置成和背景颜色一样
3.在moveX_rect(a)函数绘制移动图形之前调用cxt.translate(0,0)和drawrect1()

修改后的JS代码如下:

function drawrect(){
        var cnv=getbyid("mycanvas");
        var cxt=cnv.getContext("2d");
        cxt.strokeStyle="black";
        cxt.lineWidth=5;
        cxt.strokeRect(200,100,100,100)
   }
function drawrect1(){		//这是新定义的绘制和背景颜色一样的边框
        var cnv=getbyid("mycanvas");
        var cxt=cnv.getContext("2d");
        cxt.strokeStyle="gray";		//边框颜色和背景颜色一样
        cxt.lineWidth=5;
        cxt.strokeRect(200,100,100,100);
    }
function moveX_rect(a){
        var cnv=getbyid("mycanvas");
        var cxt=cnv.getContext("2d"); 
        cxt.translate(0,0);		
        drawrect1();		//在我们移动前,先绘制边灰色框覆盖住原先的黑色边框
        a?cxt.translate(0,-10):cxt.translate(0,10);
        drawrect();
    }

我们再来看看效果(上移三次,下移四次):

在这里插入图片描述
为什么会有黑色细边框呢??

后来我们发现,绘制的灰色边框宽度为5,原始黑色边框也为5,是这个原因导致灰色边框遮不住黑色边框呀!!所以,为了一探究竟,我们把灰色的边框宽度调整几次来看看!

我们把drawrect1()里的 “cxt.lineWith=5”改成“cxt.lineWith=3”:效果如下:
在这里插入图片描述
很明显可以看到 ‘linewith=3’ 的灰色边框盖不住‘linewith=5’的黑色边框,才会形成细细的黑色边框

所以我们在drawrect1()中,linewith一定要比原先的图形大,才能完全覆盖的住,也就是我们所看到的的清除了原先的图形

我们把linewith设置成6:就能让黑色边框自由的上下移动啦!!
在这里插入图片描述


问题解决:

解决完问题后的代码如下:

<body onload="drawrect()">
    <div>
        <button onclick="moveX_rect(1)">上移</button><button onclick="moveX_rect(0)">下移</button>
    </div>
    <canvas id="mycanvas"  width="1700px" height="800px" style="background-color:gray; border:3px black solid;"
    onmousemove="getcnvsxy(event)" onmouseout="cleanxy()"></canvas>
    <script>
        function getbyid(id){
            return document.getElementById(id);
        }
        function drawrect(){
            var cnv=getbyid("mycanvas");
            var cxt=cnv.getContext("2d");
            cxt.strokeStyle="black";
            cxt.lineWidth=5;
            cxt.strokeRect(200,100,100,100)
        }
        function drawrect1(){
            var cnv=getbyid("mycanvas");
            var cxt=cnv.getContext("2d");
            cxt.strokeStyle="gray";
            cxt.lineWidth=6;
            cxt.strokeRect(200,100,100,100);
        }
        function moveX_rect(a){
            var cnv=getbyid("mycanvas");
            var cxt=cnv.getContext("2d"); 
            cxt.translate(0,0);
            drawrect1();
            a?cxt.translate(0,-10):cxt.translate(0,10);
            drawrect();
        }
    </script>
</body>
</html>

举一反三:

我们在上下移动可以,在左右移动,旋转和放大缩小也能做到!

注意!!!

在后续的测试中我们发现若在放大和缩中会出现这种情况:

随着放大缩小的次数不断增加,盖不住的情况就会显现,也就是说,黑色细边框又会冒出来:

在这里插入图片描述

在放大与缩小中,我们发现,其实是让整个画布进行放大和缩小,所以边框的位置也会进行放大和缩小,在这种情况下,每次放大和缩小都存在着长宽按比例进行运算会出现小数,这种小数会以误差的形式展现出来,随着次数增多,误差就越大,黑色细边框就越明显。

总结

放大和缩小的问题属于个人理解和推测,具体原因大家可以进行深入的研究,在我看来,这种解决方案只适用于新手和初学者理解canvas的机制,对于多种图案移动或大型的项目制作可能不适用,此文章仅供参考!!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DlH....

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值