Web 利用 画布 canvas 自定义拖动插件

4 篇文章 0 订阅
3 篇文章 0 订阅

###自定义拖动插件
之前学习了canvas标签以及它自带的一些api,发现其实这个东西有点类似与android里的canvas,不过用法上区别还是很大的,但是在实现自定义控件/插件时候,其实原来都是一样的。

当然,我这个web的插件需要用到jquery,参考bootstrap插件开发方式,总结出有如下固定模式或者说模版

(function ($) {//闭包限定命名空间,防止全局污染
    var canvasBox = { //定义插件名称
        //初始化
        init: function (target) {
            var $target = $(target);//调用插件的标签层
            if ($target.hasClass("canvas-box")) {//增加一个自定义类
                $target.html("");
            } else {
                $target.addClass("canvas-box");
            }
            var options = $target.data("canvas-box").options;
            canvasBox.loadData($target, options.data);
            canvasBox.bindEvent($target);
        },
        //加载数据
        loadData: function ($target, data) {
            //do something
        },
        //获取数据
        getData: function (target) {
            //return something....
        },
        //绑定事件
        bindEvent: function ($target) {
            //do something...
        }
        //其他一些会用到的事件方法....
    };
//定义插件
    $.fn.canvasBox = function (options, param) {
        if (typeof options === "string") {
            return $.fn.canvasBox.methods[options](this, param);
        } else {
            $.each(this, function (index, el) {
                var opt = {};
                $.extend(opt, $.fn.canvasBox.default);
                $.extend(opt, options);
                $(this).data("canvas-box", {options: opt});
                canvasBox.init(this);
            });
        }
    };
//插件默认属性参数
    $.fn.canvasBox.defaults = {
        width: 100,
        height: 100,
        data: []
       // ....一些属性参数
    };
//插件对外提供的方法
    $.fn.canvasBox.methods = {
        getData: function (target) {
            var data = canvasBox.getData(target);
            return data;
        },
        setData: function (target, data) {
            var $target = $(target);
            canvasBox.loadData($target, data);
        }
        //可以自行增加删减需要用到的方法
    };
})(jQuery);

如上,有此固定格式,开发一些简单的插件/控件是没有什么问题的。
那么实现了插件/控件,外部调用的示例如下

html增加一div层
 <div id="canvas_box"></div>
 js代码中,获取该节点
 var $canvasBox = $("#canvas_box");
 然后实例化插件
 var data = {
                width:600,
                height:200,
                data:data//其他数据,比如数组坐标等。。。
            };
            $canvasBox.canvasBox(data);//实例化插件

知道固定的套路之后,我们就可以尝试着写一个简单的插件了
下面,我们要实现一个利用canvas拖动画布上的点,并且画布上有多个点且是一条连起来的线,拖动点时,与其相连的线也要跟着动起来。
这里写图片描述
如上图
我们需要实现的是,拖动五个红点中的其中一个,线也要跟着动起来,其实要实现这样效果的原理就是清空画布,重新绘制。这样,不停的清空和绘制,你就会发现,画布上的图是可以动起来的。
如此,知道原理了,我们就可以开始写代码了。

//插件初始化
        init: function (target) {
            var $target = $(target);//调用插件的标签层
            if ($target.hasClass("canvas-box")) {
                $target.html("");
            } else {
                $target.addClass("canvas-box");
            }
            var options = $target.data("canvas-box").options;
            var $container = $("<canvas class='canvas-container'></canvas>").appendTo($target);//嵌套一层canvas
            options.container = $container;
            $container[0].width = options.width;//获取参数的宽高值,并设置给canvas
            $container[0].height = options.height;
            if (options.backgroundImg) {//如果有背景图片
                $container.css({
                    "background-image": url(options.backgroundImg)
                })
            } else {//设置背景颜色
                $container.css({
                    "background-color": options.backgroundColor
                });
            }
            canvasBox.loadData($target, options.data);//加载数据
            canvasBox.bindEvent($target);//绑定事件
        }

实现加载方法

//加载数据
        loadData: function ($target, data) {
            var options = $target.data("canvas-box").options;
            options.data = data;
            var $container = options.container;
            var context = $container.get(0).getContext("2d");
            context.fillStyle = "red";//点颜色

            canvasBox.drawLine(context, data);//初始绘制点和线
        }

实现获取数据方法

//获取数据
        getData: function (target) {
            var $target = $(target);
            var options = $target.data("canvas-box").options;
            var data = options.data;
            return data;
        }

实现绑定事件
这里,我们需要绑定鼠标的点击事件,鼠标的移动事件以及鼠标的释放事件的监听,然后根据不同的鼠标事件来绘制我们的画布

//绑定事件
        bindEvent: function ($target) {
            var options = $target.data("canvas-box").options;
            var points = options.data;
            var $container = options.container;
            var context = $container.get(0).getContext("2d");//获取画笔
            context.fillStyle = "red";//点颜色
            //点击监听
            $container.on("mousedown", function (e) {
                var location = canvasBox.getLocation($container.get(0), e.clientX, e.clientY);//因为鼠标点击事件获取到的坐标与canvas绘图坐标不是同一个坐标系,所以需要转换一下
                var _x = location.x;
                var _y = location.y;
                var p = {x: _x, y: _y};
                console.log("鼠标点击了 " + "x:" + _x + ",y:" + _y);
                console.log("鼠标点击了2 " + "x:" + e.clientX + ",y:" + e.clientY);
                var num = canvasBox.IsOnPoint(p, points);//判断鼠标是否点击在了红点上
                var draw = false;
                if (num !== -1) {
                    draw = true;
                    //拖动监听
                    $container.on("mousemove mouseup", function (e) {
                        if (!draw) {
                            return;
                        }
                        //清空画布
                        context.clearRect(0, 0, $container.get(0).width, $container.get(0).height);
                        var location = canvasBox.getLocation($container.get(0), e.clientX, e.clientY);
                        points[num].x = location.x;
                        points[num].y = location.y;
                        canvasBox.drawLine(context, points);//重新绘制点和线
                        if (e.type === "mouseup") {
                            draw = false;
                            $container.off("mousemove mouseup");
                        }
                    });
                    $("body").on("mouseup", function (e) {//鼠标在cavas外部up后取消监听
                        draw = false;
                        $container.off("mousemove mouseup");
                    });
                }
            });
        }

其实主要的代码就这些
这样交互式的插件,实现起来的原理都差不多,可能还有许多优化的空间。
完整的demo
可以在这里下载
https://download.csdn.net/download/lakebobo/10616796
欢迎留言交流

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值