24 Jan 2018

基于canvas的图片查看器(AngularJs)

使用的函数

  1. 获取画布元素
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    
  2. 缩放图片 计算缩放比
    var initCanvas = function() {
     imgX = 0, imgY = 0;
     var canvas_a = canvas.width / canvas.height;
     var img_a = img.width / img.height;
    // 计算宽高比,进行缩放,保证初始画面全部展现在画布上
     if (img.height) {
         // 默认图片高度为0,需要默认的缩放比例 initScale;
         if (canvas_a > img_a) {
             initScale = canvas.height / img.height;
         } else {
             initScale = canvas.width / img.width;
         }
     }
     imgScale = initScale;
    }
    

    缩放

    var drawImage = function() {
     ctx.clearRect(0, 0, canvas.width, canvas.height);
     ctx.drawImage(
         img, //规定要使用的图像、画布或视频。
         0, 0, //开始剪切的 x 坐标位置。
         img.width, img.height, //被剪切图像的高度。
         imgX, imgY, //在画布上放置图像的 x 、y坐标位置。
         img.width * imgScale, img.height * imgScale //要使用的图像的宽度、高度
     );
    }
    
  3. 图片加载后渲染画布
    img = new Image();
    if (canvas.getContext) {               
     img.onload = function() {
     // 图片加载完成后调用函数
         initCanvas();
         ctx.restore(); //恢复状态
         ctx.save(); //保存状态        
         drawImage();                   
     };
     img.src = scope.getPhoto(data);
    }                    
    
  4. 图片旋转
    scope.rotate = function(angle) {
     var x = canvas.width / 2; //画布宽度的一半
     var y = canvas.height / 2; //画布高度的一半
     ctx.clearRect(0, 0, canvas.width, canvas.height); //先清掉画布上的内容
     ctx.translate(x, y); //将绘图原点移到画布中点
     ctx.rotate((Math.PI / 180) * angle); //旋转角度
     ctx.translate(-x, -y); //将画布原点移动
     drawImage(); //重新绘制图片
    }  
    
  5. 滚轮缩放
    function canvasEventsInit() {
      //事件注册
     canvas.onmousedown = function(event) {
         var pos = windowToCanvas(event.clientX, event.clientY); 
         //坐标转换,将窗口坐标转换成canvas的坐标 
         canvas.onmousemove = function(evt) { //移动
             canvas.style.cursor = 'move';
             var posl = windowToCanvas(evt.clientX, evt.clientY);
             var x = posl.x - pos.x;
             var y = posl.y - pos.y;
             pos = posl;
             imgX += x;
             imgY += y;
             drawImage(); //重新绘制图片
         };
         canvas.onmouseup = function() {
             canvas.onmousemove = null;
             canvas.onmouseup = null;
             canvas.style.cursor = 'default';
         };
     };
     canvas.onmousewheel = canvas.onwheel = function(event) { //滚轮放大缩小
         var pos = windowToCanvas(event.clientX, event.clientY);
         event.wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltalY * (-40)); //获取当前鼠标的滚动情况
         if (event.wheelDelta > 0) {
             imgScale *= 2;
             imgX = imgX * 2 - pos.x;
             imgY = imgY * 2 - pos.y;
         } else {
             imgScale /= 2;
             imgX = imgX * 0.5 + pos.x * 0.5;
             imgY = imgY * 0.5 + pos.y * 0.5;
         }
         drawImage(); //重新绘制图片
     };
     // 双击回复原状态
     canvas.ondblclick = canvas.ondblclick = function(event) {
         initCanvas();
         drawImage(); //重新绘制图片
     }
    }();
    /*坐标转换*/
    function windowToCanvas(x, y) {
     var box = canvas.getBoundingClientRect(); //这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
     return {
         x: x - box.left - (box.width - canvas.width) / 2,
         y: y - box.top - (box.height - canvas.height) / 2
     };
    }
    
  6. 位置复原
    ctx.restore(); //恢复状态
    ctx.save(); //保存状态   
    

最终代码

js代码

 app.controller('yz_eloamViewImg', ['$scope', 'concrete', 'yz_message', '$rootScope', '$broadcast',
        function(scope, concrete, yz_message, root, broadcast) {
            scope.closeModel = function() {
                broadcast("photoViewer_show", false);
                scope.$closeDialog();
            }
            scope.modal_title = '图像资料';
            scope.$on("yz_eloamViewImg", function(event, data) {
                scope.photos = data.photos.photos;
                scope.data = data.photos;
                scope.modal_title = data.photos.lable;
                scope.delFun = data.delFun;
                scope.deletePhoto = function() {
                    data.delFun(scope.data, function() {
                        if (scope.photos.length == 0) {
                            scope.closeModel();
                        } else {
                            scope.firstDraw(scope.photos[scope.photos.length - 1]);
                        }
                    });

                }
                if (scope.photos[0] && scope.photos[0].photo.name) {
                    scope.firstDraw(scope.photos[0]);
                }
            });
            var img, imgScale = 1,imgX = 0,imgY = 0,initScale = 1;
            //获取Canvas对象(画布)
            var canvas = document.getElementById("myCanvas");
            var ctx = canvas.getContext("2d");           
            var initUrl = root.uploaderInfo.fileServerLocation + "/" + root.uploaderInfo.appId + "/";
            var tokenIdUrl= "?s=" + root.uploaderInfo.tokenId;
            var uploadUrl= root.uploaderInfo.fileServerLocation + "?a=" + root.uploaderInfo.appId + "&s=" + root.uploaderInfo.tokenId;
            scope.getPhoto = function(data) {
                if (data) {
                    if (data.localImg) {
                        return data.localImg;
                    }
                    if (data.photo.resourceId) {
                        return initUrl + data.photo.resourceId + tokenIdUrl;
                    }
                } else {
                    return '/img/icon/bg1.jpg';
                }
            }
            var initCanvas = function() {
                imgX = 0, imgY = 0;
                var canvas_a = canvas.width / canvas.height;
                var img_a = img.width / img.height;
               // 计算宽高比,进行缩放,保证初始画面全部展现在画布上
                if (img.height) {
                    // 默认图片高度为0,需要默认的缩放比例 initScale;
                    if (canvas_a > img_a) {
                        initScale = canvas.height / img.height;
                    } else {
                        initScale = canvas.width / img.width;
                    }
                }
                imgScale = initScale;
            }
            img = new Image();
            if (canvas.getContext) {               
                img.onload = function() {
                // 图片加载完成后调用函数
                    initCanvas();
                    ctx.restore(); //恢复状态
                    ctx.save(); //恢复状态        
                    drawImage();
                };

            }
            scope.firstDraw = function(data) {
                scope.active = data;
                if (canvas.getContext) {
                    img.src = scope.getPhoto(data);
                }
            }
            scope.gotoPage = function(e) {
                var value = e.target.value;
                if (0 < value && value <= scope.data.count) {
                    scope.firstDraw(scope.photos[value - 1])
                }
            }
            scope.before = function() {
                var index = scope.active.sequenceNo;
                if (index < 2) {
                    return;
                }
                scope.firstDraw(scope.photos[index - 2])
            }
            scope.next = function() {
                var index = scope.active.sequenceNo;
                if (index == scope.data.count) {
                    return;
                }
                scope.firstDraw(scope.photos[index]);
            }
            var drawImage = function() {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.drawImage(
                    img, //规定要使用的图像、画布或视频。
                    0, 0, //开始剪切的 x 坐标位置。
                    img.width, img.height, //被剪切图像的高度。
                    imgX, imgY, //在画布上放置图像的 x 、y坐标位置。
                    img.width * imgScale, img.height * imgScale //要使用的图像的宽度、高度
                );
            }
            scope.rotate = function(angle) {
                var x = canvas.width / 2; //画布宽度的一半
                var y = canvas.height / 2; //画布高度的一半
                ctx.clearRect(0, 0, canvas.width, canvas.height); //先清掉画布上的内容
                ctx.translate(x, y); //将绘图原点移到画布中点
                ctx.rotate((Math.PI / 180) * angle); //旋转角度
                ctx.translate(-x, -y); //将画布原点移动
                drawImage(); //重新绘制图片
            }
            scope.recover = function() {
                ctx.restore(); //恢复状态
                ctx.save(); //记录状态
                drawImage(); //重新绘制图片
            }
            /*事件注册*/
            function canvasEventsInit() {
                canvas.onmousedown = function(event) {
                    var pos = windowToCanvas(event.clientX, event.clientY); //坐标转换,将窗口坐标转换成canvas的坐标 
                    canvas.onmousemove = function(evt) { //移动
                        canvas.style.cursor = 'move';
                        var posl = windowToCanvas(evt.clientX, evt.clientY);
                        var x = posl.x - pos.x;
                        var y = posl.y - pos.y;
                        pos = posl;
                        imgX += x;
                        imgY += y;
                        drawImage(); //重新绘制图片
                    };
                    canvas.onmouseup = function() {
                        canvas.onmousemove = null;
                        canvas.onmouseup = null;
                        canvas.style.cursor = 'default';
                    };
                };
                canvas.onmousewheel = canvas.onwheel = function(event) { //滚轮放大缩小
                    var pos = windowToCanvas(event.clientX, event.clientY);
                    event.wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltalY * (-40)); //获取当前鼠标的滚动情况
                    if (event.wheelDelta > 0) {
                        imgScale *= 2;
                        imgX = imgX * 2 - pos.x;
                        imgY = imgY * 2 - pos.y;
                    } else {
                        imgScale /= 2;
                        imgX = imgX * 0.5 + pos.x * 0.5;
                        imgY = imgY * 0.5 + pos.y * 0.5;
                    }
                    drawImage(); //重新绘制图片
                };
                canvas.ondblclick = canvas.ondblclick = function(event) {
                    initCanvas();
                    drawImage(); //重新绘制图片
                }

            }
            canvasEventsInit();
            /*坐标转换*/
            function windowToCanvas(x, y) {
                var box = canvas.getBoundingClientRect(); //这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
                return {
                    x: x - box.left - (box.width - canvas.width) / 2,
                    y: y - box.top - (box.height - canvas.height) / 2
                };
            }
        }
    ]);

html代码

<div id='pandiv'>
    <span style="display: inline-block;" ng-bind="active.remark"></span>
    <canvas id="myCanvas" width="600" height="450" style="cursor: default;background-color: rgba(237, 237, 237, 1)">您的浏览器不支持画布操作,请更新浏览器后重试!</canvas>
    <div class="row">
        <div class="col-md-12">
            <button type="button" class="btn btn-xs btn-default" ng-click="before()"><i class="fa fa-long-arrow-left"></i>上一页</button>
            <button type="button" class="btn btn-xs btn-default">当前<span ng-bind="active.sequenceNo"></span>页/共<span ng-bind="data.count"></span></button>
            <button type="button" class="btn btn-xs btn-default" ng-click="next()"><i class="fa fa-long-arrow-right"></i>下一页</button>
            <span class="btn btn-xs btn-default" style="width: 15%;">转到 <input type='text' style="width: 40%;" ng-blur="gotoPage($event)"></span>
           <a target="_blank" class="btn btn-xs btn-default" ng-href="getPhoto(active)">新窗口打开</a>
            <br/>
            <button type="button" class="btn btn-xs btn-default" ng-click="rotate(-90)"><i class="fa fa-mail-reply"></i>左旋转</button>
            <button type="button" class="btn btn-xs btn-default" ng-click="recover()"><i class="fa fa-repeat"></i>恢复</button>
            <button type="button" class="btn btn-xs btn-default" ng-click="rotate(90)"><i class="fa fa-mail-forward"></i>右旋转</button>
        </div>
    </div>
</div>

Tags: