当前位置: 首页 > 文档资料 > HTML5 Canvas 实战 >

6.8 创建图像放大器

优质
小牛编辑
135浏览
2023-12-01

本节,我们将创建一个十分优雅的图像放大器。创建方法是,根据鼠标的坐标,把大图的一部分裁剪出来,并显示在小图之上。

创建图像放大器
图6-6 创建图像放大器

操作步骤

按照以下步骤,创建一条图像放大器,当用户把鼠标移动到图像上,该放大镜渲染被放大的图像的一部分:

1. 链接到Events类:

<script src="events.js">
</script>

2. 创建一个图像加载函数,来加载小图和大图,图像加载完成后,调用回调函数:

<script>
/* 加载图像,并在图像加载完成后,把这些图像作为入参调用回调函数 */
function loadImages(sources, callback){
  var loadedImages  =  0;
  var numImages  =  0;
  var images  =  {};
  //获取图像的数目
  for  (var src in sources)  {
      numImages++;
  }
  //加载图像
  for  (var src in sources)  {
    images[src]  = new Image();
    images[src].onload  = function(){
      //图像加载完成后,调用回调函数
      if  (++loadedImages  >= numImages)  {
           callback(images);
      }
    };
    images[src].src  = sources[src];
  }
}

3. 定义drawMagnifier()函数,该函数绘制被放大的图像:

 function drawMagnifier(config){
  var context  = config.context;
  var images  = config.images;
  var mousePos  = config.mousePos;
  var imageX  = config.imageX;
  var imageY  = config.imageY;
  var magWidth  = config.magWidth;
  var magHeight  = config.magHeight;
  var smallWidth  = config.smallWidth;
  var smallHeight  = config.smallHeight;
  var largeWidth  = config.largeWidth;
  var largeHeight  = config.largeHeight;
  /* sourceX和sourceY假定我们裁剪的矩形区域在大图的内部是存在的。
   * 在放大器超过大图边缘的情况下,我们将不得不进行调整。
   */
  var sourceX  =  ((mousePos.x  - imageX)  *  largeWidth  / smallWidth)  - magWidth  /  2;
  var sourceY  =  ((mousePos.y  - imageY)  *  largeHeight  / smallHeight)  - magHeight  /  2;
  var destX  = mousePos.x  - magWidth  /  2;
  var destY  = mousePos.y  - magHeight  /  2; 
  var viewWidth  = magWidth;
  var viewHeight  = magHeight;
  var viewX  = destX;
  var viewY  = destY;
  var drawMagImage  = true;
  // 在放大器超过大图边缘的情况下,我们将进行边界检查和调整
  if  (sourceX  <  0)  {
    if  (sourceX  >  -1  * magWidth)  {
      var diffX  =  -1  * sourceX;
      viewX  += diffX;
      viewWidth  -= diffX; sourceX  =  0;
    }
    else  {
      drawMagImage  = false;
    }
  }
  if  (sourceX  > largeWidth  - magWidth)  {
    if  (sourceX  < largeWidth)  {
      viewWidth  = largeWidth  - sourceX;
    }
    else  {
      drawMagImage  = false;
    }
  }
  if  (sourceY  <  0)  {
    if  (sourceY  >  -1  * magHeight)  {
      var diffY  =  -1  * sourceY;
      viewY  += diffY;
      viewHeight  -= diffY; sourceY  =  0;
    }
    else  {
      drawMagImage  = false;
    }
  }
  if  (sourceY  > largeHeight  - magHeight)  {
    if  (sourceY  < largeHeight)  {
      viewHeight  = largeHeight  - sourceY;
    }
    else  {
      drawMagImage  = false;
    }
  }
  //绘制白色放大器背景
  context.beginPath();
  context.fillStyle  = "white";
  context.fillRect(destX, destY, magWidth, magHeight);
  // 绘制图像
  if  (drawMagImage)  {
    context.beginPath();
    context.drawImage(images.cobraLargeImg, sourceX,
    sourceY, viewWidth, viewHeight, viewX, viewY, viewWidth, viewHeight);
  }
  //绘制边框
  context.beginPath(); 
  context.lineWidth  =  2;
  context.strokeStyle  = "black";
  context.strokeRect(destX, destY, magWidth, magHeight);
}

4. 定义drawImages()函数,该函数实例化一个Events对象,并定义放大镜的属性:

function drawImages(images){
  var events  = new Events("myCanvas");
  var canvas  = events.getCanvas();
  var context  = events.getContext();
  // 定义放大镜所依赖的图像
  var imageX  = canvas.width  /  2  - images.cobraSmallImg.width  /  2;
  var imageY  = canvas.height  /  2  - images.cobraSmallImg. height  /  2;
  var magWidth  =  200; 
  var magHeight  =  150;
  var smallWidth  = images.cobraSmallImg.width;
  var smallHeight  = images.cobraSmallImg.height;
  var largeWidth  = images.cobraLargeImg.width;
  var largeHeight  = images.cobraLargeImg.height;

5. 设置stage()函数,该函数绘制小图,然后调用drawMagnifier()函数绘制被放大的图像:

events.setStage(function(){
  var mousePos  = events.getMousePos(); this.clear();
  context.drawImage(images.cobraSmallImg, imageX,
  imageY, smallWidth, smallHeight);
  // 绘制图像四周的边框
  context.beginPath();
  context.lineWidth  =  2;
  context.strokeStyle  = "black";
  context.strokeRect(imageX, imageY, smallWidth,
  smallHeight);
  context.closePath();
  if  (mousePos  !== null)  {
    drawMagnifier({
      context: context, images: images,
      mousePos: mousePos,
      imageX: imageX,
      imageY: imageY,
      magWidth: magWidth,
      magHeight: magHeight,
      smallWidth: smallWidth,
      smallHeight: smallHeight,
      largeWidth: largeWidth,
      largeHeight: largeHeight
    });
  }
});

6. 为画布元素增加事件监听器,当用户鼠标移出画布时,该监听器会重绘整个画布,以便删除被放大的图像:

canvas.addEventListener("mouseout", function(){
    events.stage();
}, false);
}

7. 页面加载完成后,创建一组图像,并以它们为入参,调用loadImages()函数:

window.onload  = function(){
  var sources  =  {
    cobraSmallImg: "cobra_280x210.jpg",
    cobraLargeImg: "cobra_800x600.jpg"
  };
  loadImages(sources, drawImages);
};
</script>

8. 在HTML文档的body部分嵌入canvas标签:

<canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
</canvas>

工作原理

要创建一个图像放大器,我们需要两幅图像,一副小图和一副大图。小图在画布上永远可见,大图将被用作绘制放大镜的缓存图像。页面加载完成后,两幅图像都被加载,我们可以实例化一个Events对象,并开始定义stage()函数。

在画布中央绘制完小图后,我们可以绘制被放大的图像。绘制方法是,计算drawImage()方法的参数sourceX, sourceY, destX, 和 destY,该方法会呈现大图被放大的部分,再把结果显示在小图上。

为了得到sourceX 和 sourceY的值,我们先计算出鼠标相对于小图的坐标(即鼠标位置和小图左上角位置的差值),再乘以放大系数(即大图的宽度除以小图的宽度),得到大图的坐标,再减去放大后的窗口尺寸的一半:

var sourceX = ((mousePos.x - imageX) * largeWidth / smallWidth) - magWidth / 2;

var sourceY = ((mousePos.y - imageY) * largeHeight / smallHeight) - magHeight / 2;

为了让放大的图像在鼠标光标的中央,我们可以让destX等于鼠标的x值减去放大后图像宽度的一半,让destY等于鼠标的y值减去放大后图像高度的一半:

var destX = mousePos.x - magWidth / 2;

var destY = mousePos.y - magHeight / 2;

相关参考

  • 第3章 绘制图像
  • 第3章 裁剪图像