中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

html5如何實現放大鏡功能

發布時間:2023-01-30 11:00:49 來源:億速云 閱讀:193 作者:iii 欄目:web開發

今天小編給大家分享一下html5如何實現放大鏡功能的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

html5實現放大鏡功能的方法:1、創建一個HTML示例文件;2、使用html5 canvas標簽初始化圖像;3、獲得canvas和image對象;4、通過“function drawAnchor() {...}”等方法將選中的區域放大,然后再繪制到原先的圖片上,保證兩塊區域的中心點一致即可。

原理

首先選擇圖片的一塊區域,然后將這塊區域放大,然后再繪制到原先的圖片上,保證兩塊區域的中心點一致, 如下圖所示:
html5如何實現放大鏡功能

初始化

<canvas id="canvas" width="500" height="500">
</canvas>

<img src="image.png" style="display: none" id="img">

獲得 canvas 和 image 對象,這里使用 <img> 標簽預加載圖片

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 函數裁剪出一個圓形區域,然后在該區域中繪制放大后的圖。一旦裁減了某個區域,以后所有的繪圖都會被限制的這個區域里,這里我們使用 saverestore 方法清除裁剪區域的影響。save 保存當前畫布的一次狀態,包含 canvas 的上下文屬性,例如 stylelineWidth 等,然后會將這個狀態壓入一個堆棧。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),那么這兩條線幾乎就會重疊在一起,如下圖所示:
html5如何實現放大鏡功能

使用圖表放大鏡的效果
html5如何實現放大鏡功能

原理

類似于地圖中的圖例,放大鏡使用較為精確的圖例,如下圖所示:
html5如何實現放大鏡功能

在放大鏡坐標系統中,原始的區域會變大,如下圖所示
html5如何實現放大鏡功能

繪制原始線段

首先創建一個線段對象

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);
       glassLines[i] = line;
   }

   scaleGlassLines = new Array(glassLineSize);
   for (var i = 0; i < glassLineSize; i++) {
       line = new Line(0, 0, 0, 0, i);
       scaleGlassLines[i] = line;
   }
}

繪制線段

function drawLines() {
   var line;
   context.lineWidth = 1;

   for (var i = 0; i < chartLines.length; i++) {
       line = chartLines[i];
       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(scaleGlassRectangle.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 = chartLines[i];

       // 判斷線段是否在放大鏡中
       if (line.xStart < xStart || line.xEnd > xEnd) {
           continue;
       }
       if (line.yEnd > yEnd || line.yStart < yStart) {
           continue;
       }

       gLine = glassLines[glassLineIndex];
       sgLine = scaleGlassLines[glassLineIndex];
       if (line.yEnd > 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 = scaleGlassLines[i].color;
       context.moveTo(scaleGlassRectangle.x + scaleGlassLines[i].xStart, scaleGlassRectangle.y + scaleGlassLines[i].yStart);
       context.lineTo(scaleGlassRectangle.x + scaleGlassLines[i].xEnd, scaleGlassRectangle.y + scaleGlassLines[i].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 = point.y;
       draw();
   }
}

canvas.onmouseup = function (e) {
   moveGlass = false;
}

鼠標雙擊

當移動到對應的線段上時,鼠標雙擊可以選擇該線段,將該線段的顏色變為紅色。

canvas.ondblclick = function (e) {
   var xStart, xEnd, yStart, yEnd;
   var clickPoint = {};
   clickPoint.x = scaleGlassRectangle.x + scaleGlassRectangle.width / 2;
   clickPoint.y = scaleGlassRectangle.y + scaleGlassRectangle.height / 2;
   var index = -1;

   for (var i = 0; i < scaleGlassLines.length; i++) {
       var scaleLine = scaleGlassLines[i];

       xStart = scaleGlassRectangle.x + scaleLine.xStart - 3;
       xEnd = scaleGlassRectangle.x + scaleLine.xStart + 3;
       yStart = scaleGlassRectangle.y + scaleLine.yStart;
       yEnd = scaleGlassRectangle.y + scaleLine.yEnd;

       if (clickPoint.x > xStart && clickPoint.x < xEnd && clickPoint.y < yStart && clickPoint.y > yEnd) {
           scaleLine.color = "#f00";
           index = scaleLine.index;
           break;
       }
   }

   for (var i = 0; i < chartLines.length; i++) {
       var line = chartLines[i];
       if (line.index == index) {
           line.color = "#f00";
       } else {
           line.color = "#888";
       }
   }

   draw();
}

鍵盤事件

因為線段離得比較近,所以使用鼠標移動很難精確的選中線段,這里使用鍵盤的w, a, s, d 來進行精確移動

document.onkeyup = function (e) {
   if (e.key == 'w') {
       centerPoint.y = intAdd(centerPoint.y, -0.2);
   }
   if (e.key == 'a') {
       centerPoint.x = intAdd(centerPoint.x, -0.2);
   }
   if (e.key == 's') {
       centerPoint.y = intAdd(centerPoint.y, 0.2);
   }
   if (e.key == 'd') {
       centerPoint.x = intAdd(centerPoint.x, 0.2);
   }
   draw();
}

以上就是“html5如何實現放大鏡功能”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

镇巴县| 沙坪坝区| 喀喇沁旗| 亚东县| 澄城县| 册亨县| 改则县| 鹤壁市| 徐州市| 五台县| 彭山县| 鄂尔多斯市| 南岸区| 西盟| 嘉祥县| 铁岭县| 榆林市| 顺义区| 衡阳市| 韩城市| 晋州市| 阜平县| 黄大仙区| 临邑县| 虞城县| 获嘉县| 台州市| 枝江市| 阿拉善盟| 遵化市| 彭山县| 民权县| 正定县| 许昌市| 吉木萨尔县| 彩票| 新丰县| 临猗县| 永兴县| 汉中市| 乌兰察布市|