Canvas:橡皮筋线条绘制

摘要:
在大多数情况下,我们需要知道的是鼠标事件发生点相对于画布的位置,而不是整个窗口中的坐标,因此我们必须执行坐标转换。
Canvas:橡皮筋线条绘制

效果演示

Canvas:橡皮筋线条绘制第1张

实现要点

事件监听

【说明】:

在Canvas中检测鼠标事件是非常简单的,可以在canvas中添加一个事件监听器,当事件发生时,浏览器就会调用这个监听器。

我们可以使用绑定事件属性:

canvas.onmousedown = function(e)
{
   //.....
}  

此外,也可以使用更为通用的addEventListener()方法来注册监听器:

canvas.addEventListener('mousedown',function(e){
   //..... 
})  

注意:使用onmouseXXX更为简单,但是addEventListener()可以向某个事件注册多个监听器。

鼠标坐标转换为canvas坐标

【说明】

  浏览器通过事件对象传递给监听器的鼠标坐标,是窗口坐标,而不是相对于canvas自身的坐标。大部分情况下,我们需要知道的是发生鼠标事件的点相对于canvas的位置,而不是在整个窗口中的坐标,所以必须进行坐标转换

Canvas:橡皮筋线条绘制第2张

【实例】:转换代码

    function windowToCanvas(x, y) {
        var bbox = canvas.getBoundingClientRect();
        return {
            x: (x - bbox.left)*(canvas.width / bbox.width),
            y: (y - bbox.top)*(canvas.height / bbox.height)
        };
    }

注意:为什么最后要乘(canvas.width / bbox.width),我们简单说明一下,canvas存在元素大小与绘图表面大小两套尺寸,我们的图像是显示在绘图表面上的,但是如果canvas元素大小较大的话,浏览器就会对绘图表面上的图像进行缩放以适应canvas元素大小,我们要避免这种缩放就要除去缩放比例

我们用element表示canvas元素,用canvas表示绘图表面,src表示绘制的内容,dest表示展示的内容

缩放规则为:dest.size = src.size * (element.size / canvas.size)

所以,src=dest.size*(canvas.size/element.size)

 绘制表面的保存与恢复

【说明】:

  使用getImageData与putImageData方法来保存与恢复绘图环境的绘图表面数据。

【实例】:保存和恢复数据

    function saveDrawingSurface() {
        drawingSurfaceImageData = context.getImageData(0, 0, canvas.width, canvas.height);
    }

    function restoreDrawingSurface() {
        context.putImageData(drawingSurfaceImageData, 0, 0);
    }  

实现代码

<canvas id="canvas">
    </canvas>
    <script>
        var canvas = document.getElementById("canvas");
        var context = canvas.getContext("2d");
        var drawingSufraceData;
        var mousedown ={};
        var dragging = false;

        //绝对坐标转相对坐标
        function windowToCanvas(x, y) {
            var bbox = canvas.getBoundingClientRect();
            return {
                x: (x - bbox.left)* (canvas.width / bbox.width),
                y: (y - bbox.top)* (canvas.height / bbox.height)
            };
        }

        //绘图表面的保存与恢复
        function saveDrawingSurface()
        {
            drawingSufraceData = context.getImageData(0,0,canvas.width,canvas.height);
        }
        function restoreDrawingSurface()
        {
            context.putImageData(drawingSufraceData,0,0);
        }

        function drawingLine(loc)
        {
            context.beginPath();
            context.moveTo(mousedown.x,mousedown.y);
            context.lineTo(loc.x,loc.y);
            context.stroke()
        }


        //鼠标按下
        canvas.onmousedown = function (e) {
            mousedown = windowToCanvas(e.x,e.y);
            saveDrawingSurface();
            dragging =true;
        }

        //鼠标移动
        canvas.onmousemove = function (e) {
            var loc =  windowToCanvas(e.x,e.y);
            if(dragging)
            {
                restoreDrawingSurface();
                drawingLine(loc);
            }
        }
        //鼠标松开
        canvas.onmouseup =function (e) {
            dragging=false;
        }
    </script>

免责声明:文章转载自《Canvas:橡皮筋线条绘制》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇AAC头部格式,RTP打包格式Django的ORM常用查询操作总结(Django编程-3)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

spring mvc 的jpa JpaRepository数据层 访问方式汇总

本文转载:http://perfy315.iteye.com/blog/1460226和http://jishiweili.iteye.com/blog/2088265 AppleFramework在数据访问控制层采用了Spring Data作为这一层的解决方案,下面就对Spring Data相关知识作一个较为详细的描述。1.Spring Data所解决的...

go-grpc 基本使用

gRPC是什么? gRPC是什么可以用官网的一句话来概括 A high-performance, open-source universal RPC framework 所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用...

前端工程中使用require.context实现前端工程自动化,批量导入路由表、批量导入svg图等场景,

require.context是什么 一个webpack的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块 什么时候需要用到require.c...

采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)

EntityFramework 非常好用,结构优美.. 但是美中有不足. 1.对动态查询条件支持的不是很好 2.批量操作支持的不是很好. 下面就是几个第三方库,对EntityFramework 的扩展.具体如何使用请百度吧.. /**********************************************/ LinqKit(免费) 动态拼...

SpringCloud入门之常用的配置文件 application.yml和 bootstrap.yml区别

SpringBoot默认支持properties和YAML两种格式的配置文件。前者格式简单,但是只支持键值对。如果需要表达列表,最好使用YAML格式。SpringBoot支持自动加载约定名称的配置文件,例如application.yml。如果是自定义名称的配置文件,就要另找方法了。可惜的是,不像前者有@PropertySource这样方便的加载方式,后者的...

context.startActivity时报错startActivity() from outside of an Activity context require the FLAG_ACTIVITY_NEW_TASK flag

源代码如下: 1 public class ReceiveHandler extendsBroadcastReceiver{ 2 3 private final String ACTION_RECE_LinkReply="com.hutao.linkRequestReceive"; 4 privateContext context; 5...