canvas图像缩小放大,canvas放大缩小

  canvas图像缩小放大,canvas放大缩小

  图片放大镜效果

  在线源预览

  源代码

  原理

  先选中图片的一个区域,然后放大这个区域,再在原图上画出来,保证两个区域的中心点一致,如下图所示:

  初始化

  canvas ID= canvas width= 500 height= 500 /canvas img src= image . png style= display:none ID= img 获取画布和图像对象。这里,IMG标签用于预加载图像。你可以在这里看到关于图像预加载。

  var canvas=document . getelementbyid( canvas );var context=canvas . get context( 2d );var img=document . getelementbyid( img );设置相关变量

  //图片放大区域的中心点也是放大镜的中心点var center point={ };//图片放大区域的半径var originalRadius=100//图片的放大面积var original rectangle={ };//放大倍数var scale=2;//放大区域varscaleglassretagle画背景图片

  函数draw background(){ context . draw image(img,0,0);}计算图片被放大的区域的范围

  这里我们用鼠标的位置作为放大区域的中心点(放大镜随鼠标移动)。因为canvas在画图的时候需要知道左上角的坐标和区域的宽高,所以我们在这里计算面积。

  函数calOriginalRectangle(point){ original rectangle . x=point . x-original radius;original rectangle . y=point . y-original radius;original rectangle . width=original radius * 2;original rectangle . height=original radius * 2;}绘制放大镜区域

  裁剪区域

  一般来说,放大镜是圆形的。这里我们用clip函数剪出一个圆形区域,然后在这个区域画一个放大的图。一旦裁剪了某个区域,以后所有绘图都将被限制在该区域内。这里,我们使用保存和恢复方法来清除裁剪区域的影响。保存当前画布的状态一次,包括画布的上下文属性,如样式、线宽等。然后将此状态推入堆栈。Restore用于恢复上次保存的状态,并从堆栈中弹出顶层状态。

  context . save();context . begin path();context.arc(centerPoint.x,centerPoint.y,originalRadius,0,Math。PI * 2,假);context.clip()。context . restore();计算放大镜区域

  通过中心点、放大区域的宽度和高度以及放大倍数,得到区域左上角的坐标和区域的宽度和高度。

  scale glass rectangle={ x:center point . x-original rectangle . width * scale/2,y:center point . y-original rectangle . height * scale/2,width:original rectangle . width * scale,height:original rectangle . height * scale }绘制图片

  这里我们用context.drawimage (img,sx,sy,swidth,sheight,x,y,width,height);方法:将画布本身作为一张图片,然后将放大区域的图像绘制到放大镜区域。

  context.drawImage(canvas,originalRectangle.x,originalRectangle.y,originalRectangle.width,originalRectangle.height,scaleGlassRectangle.x,scaleGlassRectangle.y,scaleGlassRectangle.width,scale glassrectangle . height);绘制放大边缘

  CreateRadialGradient用于绘制渐变图像。

  context . begin path();var gradient=context . createradialgradient(centerPoint.x,centerPoint.y,originalRadius - 5,center point . x,centerPoint.y,original radius);gradient.addColorStop(0, rgba(0,0,0,0,0.2));gradient.addColorStop(0.80,银色);gradient.addColorStop(0.90,银色);gradient.addColorStop(1.0, rgba(150,150,150,0.9));context.strokeStyle=gradientcontext . line width=5;context.arc(centerPoint.x,centerPoint.y,originalRadius,0,Math。PI * 2,假);context . stroke();添加鼠标事件

  为画布添加鼠标移动事件

  canvas . onmousemove=function(e){.}转换坐标

  一般鼠标得到的坐标是屏幕或者窗口的坐标,我们需要用canvas的坐标来代替。GetboundingClient用于获取页面中某个元素相对于浏览器窗口的左、上、右、下的位置。

  函数windowToCanvas(x,y){ var bbox=canvas。getboundingclientrect();return {x: x - bbox.left,y: y - bbox.top}}修改鼠标样式

  我们可以通过钢性铸铁来修改鼠标样式

  #画布{显示:块;边框:1px纯红;边距:0自动;光标:十字准线;}图表放大镜

  我们可能基于帆布绘制一些图表或者图像,如果两个元素的坐标离得比较近,就会给元素的选择带来一些影响,例如我们画两条线,一个线的坐标是(200.5, 400) - (200.5, 200),另一个线的坐标为(201.5, 400) - (201.5, 20),那么这两条线几乎就会重叠在一起,如下图所示:

  使用图表放大镜的效果

  在线演示源码

  原理

  类似于地图中的图例,放大镜使用较为精确的图例,如下图所示:

  在放大镜坐标系统中,原始的区域会变大,如下图所示

  绘制原始线段

  首先创建一个线段对象

  函数行(xStart,yStart,xEnd,yEnd,index,color) { //起点x坐标这个。x start=x start//起点y坐标这个。ys tart=ys tart//终点x坐标this.xEnd=xEnd//终点y坐标this.yEnd=yEnd//用来标记是哪条线段this.index=index//线段颜色this.color=color}初始化线段

  //原始线段var图表线条=new Array();//处于放大镜中的原始线段定义变量玻璃线;//放大后的线段定义变量刻度玻璃线;//位于放大镜中的线段数量var玻璃线尺寸函数init lines(){ var line;行=新行(200.5,400,200.5,200,0, # 888 );图表线。推(线);行=新行(201.5,400,201.5,20,1, # 888 );图表线。推(线);玻璃线条尺寸=图表线条。长度;玻璃线=新数组(玻璃线条尺寸);for(var I=0;我缩小玻璃尺寸;i ) { line=新行(0,0,0,0,I);玻璃线条[I]=线条;} scale glasslines=new Array(glassLineSize);for(var I=0;我缩小玻璃尺寸;i ) { line=新行(0,0,0,0,I);scale glass lines[I]=line;}}绘制线段

  函数drawLines(){ var line;语境。线宽=1;for(var I=0;我绘制图表。长度;I){ line=图表线[I];语境。begin path();语境。笔画样式=线条。颜色;context.moveTo(line.xStart,line。y开始);context.lineTo(line.xEnd,line。yend);语境。笔画();}}计算原始区域和放大镜区域

  函数calGlassRectangle(point){原始矩形。x=点。x-原始半径;原始矩形。y=点。y-原始半径;原始矩形。宽度=原始半径* 2;原始矩形。高度=原始半径* 2;刻度玻璃矩形。宽度=原始矩形。宽度*比例;刻度玻璃矩形。高度=原始矩形。高度*比例;刻度玻璃矩形。x=原始矩形。x原始矩形。宽度/双刻度玻璃矩形。宽度/2;刻度玻璃矩形。y=原始矩形。y原始矩形。高度/双刻度玻璃矩形。身高/2;//将值装换为整数scaleglassfrectangle。width=parse int(scaleglassfrectangle。宽度);scaleglassmrectangle。height=parse int(scaleglassmrectangle。身高);scaleglassmrectangle。x=parse int(scaleglassmrectangle。x);缩放玻璃矩形。y=parse int(scale glassrectangle。y);}计算线段在新坐标系统的位置

  由原理图我们知道,放大镜中使用坐标系的图例要比原始坐标系更加精确,比如原始坐标系使用1:100,那么放大镜坐标系使用1:10,因此我们需要重新计算线段在放大镜坐标系中的位置。同时为了简便,我们将线段的原始坐标进行了转化,减去原始区域起始的x值和y值,即将原始区域左上角的点看做为(0,0)。

  函数calScaleLines(){ var x start=原始矩形。x;var xEnd=原始矩形。x原始矩形。宽度;var yStart=original rectangle . yvar yEnd=原始矩形。y原始矩形。身高;定义变量线,gLine,sgLinevar glassline index=0;for(var I=0;我绘制图表。长度;I){ line=图表线[I];//判断线段是否在放大镜中如果(行。x开始x开始 行。xEnd xEnd){ continue;}如果(行。yEnd yEnd 行。y start y start){继续;} gLine=glassLines[glassLineIndex];SG线=刻度玻璃线[玻璃线指数];如果(行。格林娜。yEnd=yEnd}如果(行。格林娜。ys tart=ys tart} gline。x start=line。x start-x start;葛琳。ys tart=line。ys tart-ys tart;葛琳。xend=line。xend-x启动;葛琳。yend=线路。yend-ys tart;SG线。x start=parse int(gline。x start * scale);SG线。ystart=parse int(gline。ystart * scale);SG线。xend=parse int(gline。xend * scale);SG线。yend=parse int(gline。yend *标度);SG线。颜色=线条。颜色;glassLineIndex } glassLineSize=glassLineIndex }绘制放大镜中心点

  绘制放大镜中心的瞄准器

  函数绘制锚点(){ context。begin path();语境。线宽=2;context . fill style= # fff context . stroke style= # 000 context。圆弧(解析int(中心点。x),parseInt(centerPoint.y),10,0,Math .PI * 2,假);定义变量半径=15;语境。移动到(parse int(中心点。x-半径),解析int(中心点。y));语境。线到(解析int(中心点。x半径),解析int(中心点。y));语境。移动到(parse int(中心点。x),解析int(中心点。y-半径));语境。线到(解析int(中心点。x),解析int(中心点。y半径));//上下文。fill();语境。笔画();}绘制放大镜

  函数drawMagnifyingGlass(){ calScaleLines();语境。save();语境。begin path();context.arc(centerPoint.x,centerPoint.y,originalRadius,0,Math .PI * 2,假);context.clip().语境。begin path();context . fill style= # fff context . arc(center point . x,centerPoint.y,originalRadius,0,Math .PI * 2,假);语境。fill();语境。线宽=4;for(var I=0;我缩小玻璃尺寸;I){上下文。begin path();语境。stroke style=刻度玻璃线[I].颜色;语境。移动到(缩放玻璃矩形。x刻度玻璃线[I]。xStart,缩放玻璃矩形。y刻度玻璃线[I].yStart);语境。线条到(缩放玻璃矩形。x刻度玻璃线[I]。xEnd,刻度玻璃矩形。y刻度玻璃线[I].yEnd);语境。笔画();} context.restore()。语境。begin path();var渐变=上下文。createradialgradient(parseInt(center point . x),parseInt(centerPoint.y),originalRadius - 5,parse int(中心点。x)、parseInt(centerPoint.y)、原始半径);gradient.addColorStop(0.50, 0银色);gradient.addColorStop(0.90, 0银色);gradient.addColorStop(1, 1黑色);context . stroke style=gradient context。线宽=5;语境。圆弧(解析int(中心点。x),parseInt(centerPoint.y),originalRadius,0,Math .PI * 2,假);语境。笔画();绘图();}添加事件

  鼠标拖动

  鼠标移动到放大镜上,然后按下鼠标左键,可以拖动放大镜,不按鼠标左键或者不在放大镜区域都不可以拖动放大镜。

  为了实现上面的效果,我们要实现3种事件鼠标按下,鼠标移动,鼠标抬起,当鼠标按下时,检测是否在放大镜区域,如果在,设置放大镜可以移动。鼠标移动时更新放大镜中兴点的坐标。鼠标松开时,设置放大镜不可以被移动。

  画布。onmousedown=function(e){ var point=windowToCanvas(e . clientx,e . clienty);变量x1,x2,y1,y2,disx 1=point . xy1=point . yx2=center point . xy2=center point . ydis=math . pow(x2-x1,2) Math.pow(y2 - y1,2);if (dis Math.pow(originalRadius,2)){最后一点。x=点。x;最后一点。y=点。y;moveGlass=true} }画布。onmousemove=function(e){ if(移动玻璃){ var xDis,yDisvar point=windowToCanvas(e . clientx,e . clienty);xDis=点。x-最后一点。x;yDis=点。最后一点。y;center point . x=xdiscentepoint . y=yDislast点。x=点。x;最后一点。y=点。y;draw();} }画布。onmouseup=函数(e){ move glass=false;}鼠标双击

  当移动到对应的线段上时,鼠标双击可以选择该线段,将该线段的颜色变为红色。

  画布。ondblclick=function(e){ var x start,xEnd,yStart,yend var click point={ };点击点。x=缩放玻璃矩形。x刻度玻璃矩形。宽度/2;点击点。y=缩放玻璃矩形。y刻度玻璃矩形。身高/2;定义变量指数=-1;for(var I=0;I scale glasslines . length I){ var scale line=scale glasslines[I];x start=缩放玻璃矩形。x刻度线。x start-3;xEnd=刻度玻璃矩形。x刻度线。x start 3;ys tart=刻度玻璃矩形。y刻度线。ys挞;yEnd=玻璃矩形标尺。y刻度线。yEnd如果(点击点。x x开始点击点。x xEnd点击点。y y开始点击点。y yEnd){刻度线。color= # f00index=scaleLine.index打破;} } for(var I=0;我绘制图表。长度;I){ var线=图表线[I];如果(行。index==index){ line。color= # f00} else { line . color= # 888 } } draw();}键盘事件

  因为线段离得比较近,所以使用鼠标移动很难精确的选中线段,这里使用键盘的w,a,s,d来进行精确移动

  文档。onkeyup=function(e){ if(e . key== w ){中心点。y=int add(中心点。y,-0.2);} if(e . key== a ){中心点。x=int add(中心点。x,-0.2);} if(e . key== s ){中心点。y=int add(中心点。y,0.2);} if(e . key== d ){中心点。x=int add(中心点。x,0.2);} draw();}** 参考资料**

  html 5-放大玻璃

  到此这篇关于HTML5画布实现放大镜效果示例的文章就介绍到这了,更多相关HTML5画布放大镜内容请搜索以前的文章或继续浏览下面的相关文章,希望大家以后多多支持!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: