canvas系列-图片处理(五)放大镜


一.原理

当鼠标点击并移动在画布canvas中时,会显示放大后的图片一角。移除canvas,鼠标松开或是鼠标离开点击那块范围时,则不会显示。
这个原理是:把这个图片放在离屏canvas上,而可视画布canvas放着这个图片的缩小版,填充画布。
当鼠标点击这个可视画布canvas中图像的位置,我们可以根据这个位置获取离屏画布canvas中图像上的位置(这个位置是=可视画布中图像的位置*图片与可视画布canvas的倍数),此时裁剪离屏canvas中的图像,显示在可视窗口中。
二.知识点
1.图片的加载:
var img=new Image();
img.src = "timg.jpg";
img.οnlοad=function (){
context.drawImage( image , 0 , 0 );
}
2. 鼠标与canvas的交互:
 ①.鼠标点击canvas.onmousedown = function(e){e.preventDefault();}
 ②鼠标移动: 当鼠标移动到某对象范围的上方时触发的事件 
canvas.onmousemove = function(e){e.preventDefault();}
 ③鼠标按下后,松开时激发的事件
canvas.onmouseup = function(e){e.preventDefault();}
 ④当鼠标离开某对象范围时触发的事件
canvas.onmouseout = function(e){e.preventDefault();}
 e.preventDefault();//禁止默认的响应事件
3.获取在canvas里的点坐标
getBoundingClientRect()用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。
 function detect(event){
var x=event.clientX-canvas.getBoundingClientRect().left;
var y=event.clientY-canvas.getBoundingClientRect().top;
}
4.创建一个新的变量,用来判断鼠标是否处于点击的状态
var isMouseDown = false;
5.需要一个离屏画布canvas(离屏是用户不可见的),用来做放大镜的作用
<canvas id="offCanvas" style="display: none">您的浏览器尚不支持canvas</canvas>
这个canvas画布承载这是图像的大小

6.创建一个变量,用来放大的倍数,用来计算图片与可视画布canvas的倍数

var scale;

在这里我们不考虑不规则图像的倍数多样性问题,简单点,让图形的大小等于可视画布canvas的大小整数倍。

三.代码

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        body{
            background: black;
        }
        #canvas{
            display:block;
            margin:0 auto;
            border:1px solid #aaa;
        }
    </style>
</head>
<body>
    <canvas id="canvas">您的浏览器尚不支持canvas</canvas>
    <canvas id="offCanvas" style="display: none">您的浏览器尚不支持canvas</canvas>
    <script>
        var canvas = document.getElementById("canvas");
        var context = canvas.getContext("2d");

        var offCanvas = document.getElementById("offCanvas");
        var offContext = offCanvas.getContext("2d");

        var image = new Image();
        var isMouseDown = false;//用来判断鼠标是否处于点击的状态
        var scale;
        window.onload = function(){
            canvas.width = 1024;
            canvas.height = 750;

            image.src = "img-lg.jpg";
            image.onload = function(){
                offCanvas.width = image.width;
                offCanvas.height = image.height;
                //在这里我们不考虑不规则图像的倍数问题,简单点,让图形的大小等于可视画布canvas的大小3倍
                scale = offCanvas.width / canvas.width;

                context.drawImage( image , 0 , 0 , canvas.width , canvas.height );//这边放着图像的缩放版,刚刚好填充可视窗口
                offContext.drawImage( image , 0 , 0 );//offContext的大小应该跟图像的大小
             }
        }
        //1.鼠标点击
        canvas.onmousedown = function(e){
            e.preventDefault();//禁止默认的响应事件
            point = windowToCanvas( e.clientX , e.clientY );//坐标点
            console.log( point.x , point.y );
            isMouseDown = true;
           drawCanvasWithMagnifier( true , point );
        }
        //3.1鼠标移动: 当鼠标移动到某对象范围的上方时触发的事件 
        canvas.onmousemove = function(e){
            e.preventDefault();//禁止默认的响应事件
            if( isMouseDown == true ){
                point = windowToCanvas( e.clientX , e.clientY );
                console.log( point.x , point.y );
                drawCanvasWithMagnifier( true , point );
            }
        }
        //3.2鼠标按下后,松开时激发的事件
        canvas.onmouseup = function(e){
            e.preventDefault();//禁止默认的响应事件
            isMouseDown = false;
            drawCanvasWithMagnifier( false );
        }
        //3.3当鼠标离开某对象范围时触发的事件
        canvas.onmouseout = function(e){
            e.preventDefault();
            isMouseDown = false;
            drawCanvasWithMagnifier( false );
        }
        //4放大镜绘制
        //参数:isShowMagnifier是否要显示放大镜  
            //point要放大镜时,显示在哪里坐标
        function drawCanvasWithMagnifier( isShowMagnifier , point ){

            context.clearRect( 0 , 0 , canvas.width , canvas.height );
            context.drawImage( image , 0 , 0 , canvas.width , canvas.height );
            if( isShowMagnifier == true ){
                drawMagnifier( point );
            }
        }
        //5.要放大镜时,显示在哪里坐标
        function drawMagnifier( point ){
            
            var mr = 200;//设置半径值
            //离屏画布canvas中图像上的位置imageLG_cx,imageLG_cy=可视画布中图像的位置*图片与可视画布canvas的倍数
            var imageLG_cx = point.x * scale;
            var imageLG_cy = point.y * scale;

            var sx = imageLG_cx - mr;
            var sy = imageLG_cy - mr;

            var dx = point.x - mr;
            var dy = point.y - mr;

            context.save();
            context.lineWidth = 10.0
            context.strokeStyle = "#069"
            context.beginPath();
            context.arc( point.x , point.y , mr , 0 , Math.PI*2 , false );
            context.stroke();
            context.clip();

            context.drawImage( offCanvas , sx , sy , 2*mr , 2*mr , dx , dy , 2*mr , 2*mr );
            context.restore();
        }
        //2.获取在canvas里的点坐标
        //canvas在屏幕在的坐标,getBoundingClientRect()用于获取某个元素相对于视窗的位置集合。
        //集合中有top, right, bottom, left等属性。
        function windowToCanvas( x , y ){
            var bbox = canvas.getBoundingClientRect();
            return {x:x-bbox.left , y:y-bbox.top};
        }
    </script>
</body>
</html>


四.放大镜可以用五角星形


代码跟之前差不多,只要修改

//5.要放大镜时,显示在哪里坐标
        function drawMagnifier( point ){
            context.save();
            var mr = 200;//设置半径值
            //离屏画布canvas中图像上的位置imageLG_cx,imageLG_cy=可视画布中图像的位置*图片与可视画布canvas的倍数
            var imageLG_cx = point.x * scale;
            var imageLG_cy = point.y * scale;

            var sx = imageLG_cx - mr;
            var sy = imageLG_cy - mr;

            var dx = point.x - mr;
            var dy = point.y - mr;

            context.save();
            context.lineWidth = 10.0;
            context.translate(point.x ,point.y);
            context.scale(mr,mr);
            starPath(context);
            context.fillStyle="#fff";
            context.fill();
            context.restore();
            context.clip();

            context.drawImage( offCanvas , sx , sy , 2*mr , 2*mr , dx , dy , 2*mr , 2*mr );
            context.restore();
        }
        //五角星
        function starPath(ctx){//参数:canvas的内容传递,小圆半径,大圆半径,原点坐标的转移位置x,y,旋转的角度
            ctx.beginPath();
            for(var i=0;i<5;i++){
                ctx.lineTo(Math.cos(2*(18+i*72)*Math.PI / 360),
                            -Math.sin(2*(18+i*72)*Math.PI / 360));
                ctx.lineTo(Math.cos(2*(54+i*72)*Math.PI / 360)*0.5,
                            -Math.sin(2*(54+i*72)*Math.PI / 360)*0.5);
            }
           context.closePath();
        }


五.不足

如果是用户上传图像,这时图像大小就不确定,倍数得情况就多样性了,而此项目并没有考虑这些而是简单化了,事先就把图像大小设计成可视画布canvas的整数倍(3倍),。

欢迎大家一起讨论,解决这些不足,使其项目更加完整。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值