• canvas练习单个矩形形变


    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style>
        .mydraw{display:block;border:1px solid #ccc;position:relative;margin:0 auto;}
        </style>
    </head>
    <body>
        <canvas class="mydraw" id="mycanvas">您的浏览器不支持canvas</canvas>
    </body>
    <script>
        window.onload=function(){
            var vary=new Vary("#mycanvas");
            vary.init();
        }
        function Vary(el,options){
            this.canvas=typeof el =='string' ? document.querySelector(el) : el;
            this.ctx=this.canvas.getContext("2d");
            this.options=extend({},[options,{w:1000,//canvas的宽度
                h:800,//canvas的高度
                dis:10,//控制区域的范围(单位像素)
                r_w:200,//矩形的初始宽度
                r_h:200,//矩形的初始高度
                fillStyle:"#0bac5a",
                strokeStyle:"#0bac5a",
                strokeWidth:2}]);
            this.pathes=[];//控制区域路径信息
            this.px;//鼠标点击位置
            this.py;//鼠标点击位置
            this.pos;//控制区域编号
            this.isMove=false;
            this.rec={};
            this.min=0;
        }
        Vary.prototype.down=function(_this,event){
            _this.px=event.offsetX || event.layerX,
            _this.py=event.offsetY || event.layerY;
            _this.isMove=true;
        }
        Vary.prototype.move=function(_this,event){
            var now_x=event.offsetX || event.layerX,
                now_y=event.offsetY || event.layerY;
            if(_this.isMove){
                var delta_x=now_x-_this.px,
                    delta_y=now_y-_this.py,
                    stat=-1;//当前的pos
                if(_this.pos==0){
                    _this.rec.init(delta_x,delta_y, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==1){
                    if(_this.options.r_w<=_this.min && _this.options.r_h>_this.min){
                        stat=2;
                    }else if(_this.options.r_h<=_this.min && _this.options.r_w>_this.min){
                        stat=3;
                    }else if(_this.options.r_h<=_this.min && _this.options.r_w<=_this.min){
                        stat=4;
                    }else{
                        stat=1;
                    }
                    _this.options.r_w-=delta_x;
                    _this.options.r_h-=delta_y;
                    _this.rec.init(delta_x,delta_y, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==4){
                    if(_this.options.r_w<=_this.min&&_this.options.r_h>_this.min){
                        stat=3;
                    }else if(_this.options.r_h<=_this.min&&_this.options.r_w>_this.min){
                        stat=2
                    }else if(_this.options.r_w<=_this.min && _this.options.r_h<=_this.min){
                        stat=1;
                    }else{
                        stat=4;
                    }
                    _this.options.r_w+=delta_x;
                    _this.options.r_h+=delta_y;
                    _this.rec.init(0, 0, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==2){
                    if(_this.options.r_w<=_this.min&&_this.options.r_h>_this.min){
                        stat=1;
                    }else if(_this.options.r_h<=_this.min&&_this.options.r_w>_this.min){
                        stat=4;
                    }else if(_this.options.r_h<=_this.min&&_this.options.r_w<=_this.min){
                        stat=3;
                    }else{
                        stat=2;
                    }
                    _this.options.r_w+=delta_x;
                    _this.options.r_h-=delta_y;
                    _this.rec.init(0, delta_y, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==3){
                    if(_this.options.r_w<=_this.min&&_this.options.r_h>_this.min){
                        stat=4;
                    }else if(_this.options.r_h<=_this.min&&_this.options.r_w>_this.min){
                        stat=1;
                    }else if(_this.options.r_w<=_this.min&&_this.options.r_h<=_this.min){
                        stat=2;
                    }else{
                        stat=3;
                    }
                    _this.options.r_w-=delta_x;
                    _this.options.r_h+=delta_y;
                    _this.rec.init(delta_x, 0, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==5){
                    _this.options.r_h<0?stat=6:stat=5;
                    _this.options.r_h-=delta_y;
                    _this.rec.init(0, delta_y, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==6){
                    _this.options.r_h<0?stat=5:stat=6;
                    _this.options.r_h+=delta_y;
                    _this.rec.init(0, 0, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==7){
                    _this.options.r_w<0?stat=8:stat=7;
                    _this.options.r_w-=delta_x;
                    _this.rec.init(delta_x,0, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }else if(_this.pos==8){
                    _this.options.r_w<0?stat=7:stat=8;
                    _this.options.r_w+=delta_x;
                    _this.rec.init(0,0, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                }
                changeMouse(this.canvas,stat);
                _this.rec.draw(_this.ctx,_this.options.w,_this.options.h);
                _this.px=now_x;
                _this.py=now_y;
                changePath(_this.rec.x, _this.rec.y, _this.rec.w, _this.rec.h, _this.options.dis,_this.pathes);
            }else{
                _this.pos=getPos(now_x, now_y, _this.ctx, _this.pathes);//移动的时候就不能再重新获取位置了
                changeMouse(this.canvas,_this.pos);
            }
        }
        Vary.prototype.up=function(_this){
            _this.isMove=false;
            var ww=0,hh=0;
            if(_this.rec.w<0 || _this.rec.h<0){
                if(_this.rec.w<0&&_this.rec.h>0){
                    ww=_this.rec.w;hh=0;
                }else if(_this.rec.w<0&&_this.rec.h<0){
                    ww=_this.rec.w;hh=_this.rec.h;
                }else if(_this.rec.w>0&&_this.rec.h<0){
                    ww=0;hh=_this.rec.h;
                }
                _this.options.r_w=Math.abs(_this.options.r_w);
                _this.options.r_h=Math.abs(_this.options.r_h);
                _this.rec.init(ww, hh, _this.options.w, _this.options.h, _this.options.r_w, _this.options.r_h);
                _this.rec.draw(_this.ctx,_this.options.w,_this.options.h);
            }
            changePath(_this.rec.x, _this.rec.y, _this.rec.w, _this.rec.h, _this.options.dis,_this.pathes);
        }
        Vary.prototype.init=function(){
            this.canvas.width=this.options.w;
            this.canvas.height=this.options.h;
            this.rec=new Rect(this.options.w, this.options.h, this.options.r_w, this.options.r_h);
            this.rec.init(0, 0, this.options.w, this.options.h, this.options.r_w, this.options.r_h);
            this.rec.draw(this.ctx,this.options.w,this.options.h);
            changePath(this.rec.x,this.rec.y,this.rec.w,this.rec.h,this.options.dis,this.pathes);
            var self=this;
            this.canvas.onmousedown=function(event){
                self.down(self,event);
            }
            this.canvas.onmousemove=function(event){
                self.move(self,event);
            }
            this.canvas.onmouseout=this.canvas.onmouseup=function(){
                self.up(self);
            }
        }
        /*
        *  创建变幻矩形
         */
        var Rect=function(w,h,r_w,r_h){
            this.x=w/2-r_w/2;
            this.y=h/2-r_h/2;
            this.delta_x;
            this.delta_y;
            this.w;
            this.h;
        }
        // 初始化,变幻过程中改变宽高,起始坐标等
        Rect.prototype.init=function(delta_x,delta_y,w,h,r_w,r_h){
            if(typeof delta_x=="number" && typeof delta_y=="number" ){
                this.delta_x=delta_x;
                this.delta_y=delta_y;
                this.x=this.x+this.delta_x;
                this.y=this.y+this.delta_y;
                if(this.x<0){
                    this.x=0;
                }
                if(this.y<0){
                    this.y=0;
                }
                if(this.x>w-r_w){
                    this.x=w-r_w;
                }
                if(this.y>h-r_h){
                    this.y=h-r_h;
                }
                this.w=r_w;
                this.h=r_h;
            }else{
                alert("参数类型错误");
            }
        }
        // 绘制矩形
        Rect.prototype.draw=function(ctx,w,h){
            ctx.strokeStyle="#0bac5a"
            ctx.clearRect(0,0,w,h);
            ctx.strokeRect(this.x,this.y,this.w,this.h);
        }
        /*
         * [changePath 得到鼠标操作区域数组]
         * @param  {[number]} x      [canvas变幻矩形的起始坐标x]
         * @param  {[number]} y      [canvas变幻矩形的起始坐标y]
         * @param  {[number]} w      [canvas变幻矩形的宽度]
         * @param  {[number]} h      [canvas变幻矩形的高度]
         * @param  {[number]} dis    [鼠标操作区域的尺寸]
         * @param  {[array]} pathes [鼠标操作区域矩形坐标数组]
         */
        function changePath(x,y,w,h,dis,pathes){
            if(typeof x=="number" && typeof y=="number" && typeof w=="number" && typeof w=="number" && typeof dis=="number"){
                pathes[0]={x:x+dis,y:y+dis,w:w-2*dis,h:h-2*dis};//拖动
                pathes[1]={x:x-dis,y:y-dis,w:dis*2,h:dis*2}//改变大小---左上角
                pathes[2]={x:x+w-dis,y:y-dis,w:dis*2,h:dis*2}//改变大小---右上角
                pathes[3]={x:x-dis,y:y+h-dis,w:dis*2,h:dis*2}//改变大小---左下角
                pathes[4]={x:x+w-dis,y:y+h-dis,w:dis*2,h:dis*2}//改变大小---右下角
                pathes[5]={x:x+dis,y:y-dis,w:w-2*dis,h:dis*2}//改变大小---上
                pathes[6]={x:x+dis,y:y+h-dis,w:w-2*dis,h:dis*2}//改变大小---下
                pathes[7]={x:x-dis,y:y+dis,w:dis*2,h:h-dis*2}//改变大小---左
                pathes[8]={x:x+w-dis,y:y+dis,w:dis*2,h:h-dis*2}//改变大小---右
            }
        }
        /*
         * [getPos 获得鼠标所在区域]
         * @param  {[number]} x      [鼠标在画布上的位置x]
         * @param  {[number]} y      [鼠标在画布上的位置y]
         * @param  {[obj]} ctx    [canvas画布对象]
         * @param  {[array]} pathes [鼠标操作区域矩形坐标数组]
         * @return {[number]}        [代表鼠标位置的数字]
         */
        function getPos(x,y,ctx,pathes){
            if(typeof x=="number" && typeof y=="number"){
                var pos=-1;
                for(var i=0,ln=pathes.length;i<ln;i++){
                    ctx.beginPath();
                    ctx.rect(pathes[i].x,pathes[i].y,pathes[i].w,pathes[i].h);
                    if(ctx.isPointInPath(x,y)){
                        pos=i;
                        break;
                    }
                }
                return pos;
            }
        }
        /*
         *  [changeMouse 获取鼠标样式]
         *  @param  {[obj]} canvas [canvas Dom对象]
         * @param  {[number]} pos    [位置值]
         * @return {[string]}        [鼠标样式]
         */
        function changeMouse(canvas,pos){
            if(typeof pos == "number" && pos>=-1 && pos<9){
                var cursor="";
                switch(pos){
                    case 0: cursor="move";break;
                    case 1: cursor="nw-resize";break;
                    case 2: cursor="ne-resize";break;
                    case 3: cursor="sw-resize";break;
                    case 4: cursor="se-resize";break;
                    case 5: cursor="n-resize";break;
                    case 6: cursor="s-resize";break;
                    case 7: cursor="w-resize";break;
                    case 8: cursor="e-resize";break;
                    default: cursor="default";
                }
                canvas.style.cursor=cursor;
            }
        }
        /**
         * [extend 合并Json数据]
         * @param  {[Json]} des             [已有的Json]
         * @param  {[Json]} src              [Json]
         * @param  {[Json]} override    [要合并的Json]
         * @return   {[Json]}                [返回合并后的des]
         */
        function extend(des, src, override){
            if(src instanceof Array){
                for(var i = 0, len = src.length; i < len; i++)
                extend(des, src[i], override);
            }
            for( var i in src){
                if(override || !(i in des)){
                    des[i] = src[i];
                }
            }
            return des;
        }
    </script>
    </html>

    红色线以及其内部是变幻矩形的区域 绿色小方块是四个角的操作区域,可以同时改变宽高 黄色部分是通过边来单一改变矩形宽高的 将这些区域的路径数据值宽高存到pathes数组中,并且以他们的索引值作为代号 通过isPointInPath() 这个函数判断鼠标在哪个路径里面,然后进行相应的操作,包括:改变鼠标的样式,和所执行的变换操作。 相反方向改变大小的时候宽度会出现负值,拖动过程中不用理会,等mouseup的时候处理就行

  • 相关阅读:
    设计模式之观察者模式
    设计模式之外观模式
    设计模式之模板模式
    设计模式之装饰器模式
    设计模式之代理模式
    .NET常见问题汇总
    使用位运算计算两个整数的加减
    一个程序判断CPU是大端还是小端
    后缀表达式 转 表达式树
    实习一个月的小结
  • 原文地址:https://www.cnblogs.com/youzhuxiaoyao/p/6861678.html
Copyright © 2020-2023  润新知