




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Canvas 实现放大镜效果原理首先选择图片的一块区域,然后将这块区域放大,然后再绘制到原先的图片上,保证两块区域的中心点一致, 如下图所示:初始化获得 canvas 和 image 对象,这里使用 标签预加载图片, 关于图片预加载可以看这里var canvas = document.getElementById(canvas);var context = canvas.getContext(2d);var img = document.getElementById(img);设置相关变量/ 图片被放大区域的中心点,也是放大镜的中心点var centerPoint = ;/ 图片被放大区域的半径var originalRadius = 100;/ 图片被放大区域var originalRectangle = ;/ 放大倍数var scale = 2;/ 放大后区域var scaleGlassRectangle画背景图片function drawBackGround() context.drawImage(img, 0, 0);计算图片被放大的区域的范围这里我们使用鼠标的位置作为被放大区域的中心点(放大镜随着鼠标移动而移动),因为 canvas 在画图片的时候,需要知道左上角的坐标以及区域的宽高,所以这里我们计算区域的范围function calOriginalRectangle(point) originalRectangle.x = point.x - originalRadius; originalRectangle.y = point.y - originalRadius; originalRectangle.width = originalRadius * 2; originalRectangle.height = originalRadius * 2;绘制放大镜区域裁剪区域放大镜一般是圆形的,这里我们使用 clip 函数裁剪出一个圆形区域,然后在该区域中绘制放大后的图。一旦裁减了某个区域,以后所有的绘图都会被限制的这个区域里,这里我们使用 save 和 restore 方法清除裁剪区域的影响。save 保存当前画布的一次状态,包含 canvas 的上下文属性,例如 style,lineWidth 等,然后会将这个状态压入一个堆栈。restore 用来恢复上一次 save 的状态,从堆栈里弹出最顶层的状态。context.save();context.beginPath();context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);context.clip();.context.restore();计算放大镜区域通过中心点、被放大区域的宽高以及放大倍数,获得区域的左上角坐标以及区域的宽高。scaleGlassRectangle = x: centerPoint.x - originalRectangle.width * scale / 2, y: centerPoint.y - originalRectangle.height * scale / 2, width: originalRectangle.width * scale, height: originalRectangle.height * scale绘制图片在这里我们使用 context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height); 方法,将 canvas 自身作为一副图片,然后取被放大区域的图像,将其绘制到放大镜区域里。context.drawImage(canvas, originalRectangle.x, originalRectangle.y, originalRectangle.width, originalRectangle.height, scaleGlassRectangle.x, scaleGlassRectangle.y, scaleGlassRectangle.width, scaleGlassRectangle.height);绘制放大边缘createRadialGradient 用来绘制渐变图像context.beginPath();var gradient = context.createRadialGradient( centerPoint.x, centerPoint.y, originalRadius - 5, centerPoint.x, centerPoint.y, originalRadius);gradient.addColorStop(0, rgba(0,0,0,0.2);gradient.addColorStop(0.80, silver);gradient.addColorStop(0.90, silver);gradient.addColorStop(1.0, rgba(150,150,150,0.9);context.strokeStyle = gradient;context.lineWidth = 5;context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);context.stroke();添加鼠标事件为 canvas 添加鼠标移动事件canvas.onmousemove = function (e) .转换坐标鼠标事件获得坐标一般为屏幕的或者 window 的坐标,我们需要将其装换为 canvas 的坐标。getBoundingClientRect 用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。function windowToCanvas(x, y) var bbox = canvas.getBoundingClientRect(); return x: x - bbox.left, y: y - bbox.top修改鼠标样式我们可以通过 css 来修改鼠标样式#canvas display: block; border: 1px solid red; margin: 0 auto; cursor: crosshair;图表放大镜我们可能基于 canvas 绘制一些图表或者图像,如果两个元素的坐标离得比较近,就会给元素的选择带来一些影响,例如我们画两条线,一个线的坐标是(200.5, 400) - (200.5, 200),另一个线的坐标为 (201.5, 400) - (201.5, 20),那么这两条线几乎就会重叠在一起,如下图所示:使用图表放大镜的效果在线演示 源码原理类似于地图中的图例,放大镜使用较为精确的图例,如下图所示:在放大镜坐标系统中,原始的区域会变大,如下图所示绘制原始线段首先创建一个线段对象function Line(xStart, yStart, xEnd, yEnd, index, color) / 起点x坐标 this.xStart = xStart; / 起点y坐标 this.yStart = yStart; / 终点x坐标 this.xEnd = xEnd; / 终点y坐标 this.yEnd = yEnd; / 用来标记是哪条线段 this.index = index; / 线段颜色 this.color = color;初始化线段/ 原始线段var chartLines = new Array();/ 处于放大镜中的原始线段var glassLines;/ 放大后的线段var scaleGlassLines;/ 位于放大镜中的线段数量var glassLineSize;function initLines() var line; line = new Line(200.5, 400, 200.5, 200, 0, #888); chartLines.push(line); line = new Line(201.5, 400, 201.5, 20, 1, #888); chartLines.push(line); glassLineSize = chartLines.length; glassLines = new Array(glassLineSize); for (var i = 0; i glassLineSize; i+) line = new Line(0, 0, 0, 0, i); glassLinesi = line; scaleGlassLines = new Array(glassLineSize); for (var i = 0; i glassLineSize; i+) line = new Line(0, 0, 0, 0, i); scaleGlassLinesi = line; 绘制线段function drawLines() var line; context.lineWidth = 1; for (var i = 0; i chartLines.length; i+) line = chartLinesi; context.beginPath(); context.strokeStyle = line.color; context.moveTo(line.xStart, line.yStart); context.lineTo(line.xEnd, line.yEnd); context.stroke(); 计算原始区域和放大镜区域function calGlassRectangle(point) originalRectangle.x = point.x - originalRadius; originalRectangle.y = point.y - originalRadius; originalRectangle.width = originalRadius * 2; originalRectangle.height = originalRadius * 2; scaleGlassRectangle.width = originalRectangle.width * scale; scaleGlassRectangle.height = originalRectangle.height * scale; scaleGlassRectangle.x = originalRectangle.x + originalRectangle.width / 2 - scaleGlassRectangle.width / 2; scaleGlassRectangle.y = originalRectangle.y + originalRectangle.height / 2 - scaleGlassRectangle.height / 2; / 将值装换为整数 scaleGlassRectangle.width = parseInt(scaleGlassRectangle.width); scaleGlassRectangle.height = parseInt(scaleGlassRectangle.height); scaleGlassRectangle.x = parseInt(scaleGRectangle.x); scaleGlassRectangle.y = parseInt(scaleGlassRectangle.y);计算线段在新坐标系统的位置由原理图我们知道,放大镜中使用坐标系的图例要比原始坐标系更加精确,比如原始坐标系使用 1:100,那么放大镜坐标系使用 1:10,因此我们需要重新计算线段在放大镜坐标系中的位置。同时为了简便,我们将线段的原始坐标进行了转化,减去原始区域起始的x值和y值,即将原始区域左上角的点看做为(0,0)。function calScaleLines() var xStart = originalRectangle.x; var xEnd = originalRectangle.x + originalRectangle.width; var yStart = originalRectangle.y; var yEnd = originalRectangle.y + originalRectangle.height; var line, gLine, sgLine; var glassLineIndex = 0; for (var i = 0; i chartLines.length; i+) line = chartLinesi; / 判断线段是否在放大镜中 if (line.xStart xEnd) continue; if (line.yEnd yEnd | line.yStart yEnd) gLine.yEnd = yEnd; if (line.yStart yStart) gLine.yStart = yStart; gLine.xStart = line.xStart - xStart; gLine.yStart = line.yStart - yStart; gLine.xEnd = line.xEnd - xStart; gLine.yEnd = line.yEnd - yStart; sgLine.xStart = parseInt(gLine.xStart * scale); sgLine.yStart = parseInt(gLine.yStart * scale); sgLine.xEnd = parseInt(gLine.xEnd * scale); sgLine.yEnd = parseInt(gLine.yEnd * scale); sgLine.color = line.color; glassLineIndex+; glassLineSize = glassLineIndex;绘制放大镜中心点绘制放大镜中心的瞄准器function drawAnchor() context.beginPath(); context.lineWidth = 2; context.fillStyle = #fff; context.strokeStyle = #000; context.arc(parseInt(centerPoint.x), parseInt(centerPoint.y), 10, 0, Math.PI * 2, false); var radius = 15; context.moveTo(parseInt(centerPoint.x - radius), parseInt(centerPoint.y); context.lineTo(parseInt(centerPoint.x + radius), parseInt(centerPoint.y); context.moveTo(parseInt(centerPoint.x), parseInt(centerPoint.y - radius); context.lineTo(parseInt(centerPoint.x), parseInt(centerPoint.y + radius); /context.fill(); context.stroke();绘制放大镜function drawMagnifyingGlass() calScaleLines(); context.save(); context.beginPath(); context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false); context.clip(); context.beginPath(); context.fillStyle = #fff; context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false); context.fill(); context.lineWidth = 4; for (var i = 0; i glassLineSize; i+) context.beginPath(); context.strokeStyle = scaleGlassLinesi.color; context.moveTo(scaleGlassRectangle.x + scaleGlassLinesi.xStart, scaleGlassRectangle.y + scaleGlassLinesi.yStart); context.lineTo(scaleGlassRectangle.x + scaleGlassLinesi.xEnd, scaleGlassRectangle.y + scaleGlassLinesi.yEnd); context.stroke(); context.restore(); context.beginPath(); var gradient = context.createRadialGradient( parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius - 5, parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius); gradient.addColorStop(0.50, silver); gradient.addColorStop(0.90, silver); gradient.addColorStop(1, black); context.strokeStyle = gradient; context.lineWidth = 5; context.arc(parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius, 0, Math.PI * 2, false); context.stroke(); drawAnchor();添加事件鼠标拖动鼠标移动到放大镜上,然后按下鼠标左键,可以拖动放大镜,不按鼠标左键或者不在放大镜区域都不可以拖动放大镜。为了实现上面的效果,我们要实现3种事件 mousedown, mousemove, mouseup, 当鼠标按下时,检测是否在放大镜区域,如果在,设置放大镜可以移动。鼠标移动时更新放大镜中兴点的坐标。鼠标松开时,设置放大镜不可以被移动。canvas.onmousedown = function (e) var point = windowToCanvas(e.clientX, e.clientY); var x1, x2, y1, y2, dis; x1 = point.x; y1 = point.y; x2 = centerPoint.x; y2 = centerPoint.y; dis = Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2); if (dis Math.pow(originalRadius, 2) lastPoint.x = point.x; lastPoint.y = point.y; moveGlass = true; canvas.onmousemove = function (e) if (moveGlass) var xDis, yDis; var point = windowToCanvas(e.clientX, e.clientY); xDis = point.x - lastPoint.x; yDis = point.y - lastPoint.y; centerPoint.x += xDis; centerPoint.y += yDis; lastPoint.x = point.x; lastPoint.y = poin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 私立幼儿园股权出售与幼儿教育质量监督及评估合同
- 天津市安全员及答案
- 农村会议考试试题及答案
- 学院奖榄菊获奖营销方案
- 2025年微电网群储能系统与新能源发电协同优化配置研究报告
- 温岭活动策划方案收费标准
- 2025年皮革涂饰考试题目及答案
- 2025年山西英语中考真题及答案
- 5.18 轮轴的秘密(教学设计)2023-2024学年五年级下册科学冀人版
- 开学说课稿-2025-2026学年中职基础课-数学工具与数学建模专题-高教版(2021)-(数学)-51
- 园林工程量计算培训
- 道路运输行业安全培训课件
- 大模型+智能交通高效出行与城市治理可行性分析报告
- 2025年民事诉讼法试题及答案
- 26年中考数学几何模型解读与训练专题33圆中的重要模型之圆幂定理模型(学生版+名师详解版)
- 吉利汽车2025年并购后的企业转型与市场竞争力提升报告
- 煤气罐起火安全培训课件
- 攀岩课件教学课件
- GB/T 46150.1-2025锅炉和压力容器第1部分:性能要求
- 食品肉类供货合同范本
- SPSS操作课件教学课件
评论
0/150
提交评论