婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > HTML5 Canvas實現(xiàn)放大鏡效果示例

HTML5 Canvas實現(xiàn)放大鏡效果示例

熱門標簽:如何獲取地圖標注客戶 機器人外呼系統(tǒng)存在哪些能力 拓展地圖標注 電話機器人電銷系統(tǒng)掙話費 高德地圖標注地點糾錯 平?jīng)龅貓D標注位置怎么弄 電話機器人黑斑馬免費 南昌仁和怎么申請開通400電話 只辦理400電話

圖片放大鏡效果

在線源碼預覽

源碼

原理

首先選擇圖片的一塊區(qū)域,然后將這塊區(qū)域放大,然后再繪制到原先的圖片上,保證兩塊區(qū)域的中心點一致, 如下圖所示:

初始化

<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");

設置相關變量

// 圖片被放大區(qū)域的中心點,也是放大鏡的中心點
var centerPoint = {};
// 圖片被放大區(qū)域的半徑
var originalRadius = 100;
// 圖片被放大區(qū)域
var originalRectangle = {};
// 放大倍數(shù)
var scale = 2;
// 放大后區(qū)域
var scaleGlassRectangle

畫背景圖片

function drawBackGround() {
    context.drawImage(img, 0, 0);
}

計算圖片被放大的區(qū)域的范圍

這里我們使用鼠標的位置作為被放大區(qū)域的中心點(放大鏡隨著鼠標移動而移動),因為 canvas 在畫圖片的時候,需要知道左上角的坐標以及區(qū)域的寬高,所以這里我們計算區(qū)域的范圍

function calOriginalRectangle(point) {
    originalRectangle.x = point.x - originalRadius;
    originalRectangle.y = point.y - originalRadius;
    originalRectangle.width = originalRadius * 2;
    originalRectangle.height = originalRadius * 2;
}

繪制放大鏡區(qū)域

裁剪區(qū)域

放大鏡一般是圓形的,這里我們使用 clip 函數(shù)裁剪出一個圓形區(qū)域,然后在該區(qū)域中繪制放大后的圖。一旦裁減了某個區(qū)域,以后所有的繪圖都會被限制的這個區(qū)域里,這里我們使用 saverestore 方法清除裁剪區(qū)域的影響。save 保存當前畫布的一次狀態(tài),包含 canvas 的上下文屬性,例如 stylelineWidth 等,然后會將這個狀態(tài)壓入一個堆棧。restore 用來恢復上一次 save 的狀態(tài),從堆棧里彈出最頂層的狀態(tài)。

context.save();
context.beginPath();
context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);
context.clip();
......
context.restore();

計算放大鏡區(qū)域

通過中心點、被放大區(qū)域的寬高以及放大倍數(shù),獲得區(qū)域的左上角坐標以及區(qū)域的寬高。

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 自身作為一副圖片,然后取被放大區(qū)域的圖像,將其繪制到放大鏡區(qū)域里。

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) {
    ......
}

轉(zhuǎn)換坐標

鼠標事件獲得坐標一般為屏幕的或者 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),那么這兩條線幾乎就會重疊在一起,如下圖所示:

使用圖表放大鏡的效果

在線演示    源碼

原理

類似于地圖中的圖例,放大鏡使用較為精確的圖例,如下圖所示:

在放大鏡坐標系統(tǒng)中,原始的區(qū)域會變大,如下圖所示

繪制原始線段

首先創(chuàng)建一個線段對象

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;
// 位于放大鏡中的線段數(shù)量
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();
    }
}

計算原始區(qū)域和放大鏡區(qū)域

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;

    // 將值裝換為整數(shù)
    scaleGlassRectangle.width = parseInt(scaleGlassRectangle.width);
    scaleGlassRectangle.height = parseInt(scaleGlassRectangle.height);
    scaleGlassRectangle.x = parseInt(scaleGlassRectangle.x);
    scaleGlassRectangle.y = parseInt(scaleGlassRectangle.y);
}

計算線段在新坐標系統(tǒng)的位置

由原理圖我們知道,放大鏡中使用坐標系的圖例要比原始坐標系更加精確,比如原始坐標系使用 1:100,那么放大鏡坐標系使用 1:10,因此我們需要重新計算線段在放大鏡坐標系中的位置。同時為了簡便,我們將線段的原始坐標進行了轉(zhuǎn)化,減去原始區(qū)域起始的x值和y值,即將原始區(qū)域左上角的點看做為(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();
}

添加事件

鼠標拖動

鼠標移動到放大鏡上,然后按下鼠標左鍵,可以拖動放大鏡,不按鼠標左鍵或者不在放大鏡區(qū)域都不可以拖動放大鏡。
為了實現(xiàn)上面的效果,我們要實現(xiàn)3種事件 mousedown, mousemove, 'mouseup', 當鼠標按下時,檢測是否在放大鏡區(qū)域,如果在,設置放大鏡可以移動。鼠標移動時更新放大鏡中興點的坐標。鼠標松開時,設置放大鏡不可以被移動。

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;
}

鼠標雙擊

當移動到對應的線段上時,鼠標雙擊可以選擇該線段,將該線段的顏色變?yōu)榧t色。

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-MagnifyingGlass

到此這篇關于HTML5 Canvas實現(xiàn)放大鏡效果示例的文章就介紹到這了,更多相關HTML5 Canvas放大鏡內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持腳本之家!

標簽:新疆 西藏 永州 棗莊 青島 池州 漯河 遼源

巨人網(wǎng)絡通訊聲明:本文標題《HTML5 Canvas實現(xiàn)放大鏡效果示例》,本文關鍵詞  HTML5,Canvas,實現(xiàn),放大鏡,;如發(fā)現(xiàn)本文內(nèi)容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《HTML5 Canvas實現(xiàn)放大鏡效果示例》相關的同類信息!
  • 本頁收集關于HTML5 Canvas實現(xiàn)放大鏡效果示例的相關信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    久热成人在线视频| 久久久午夜电影| 亚洲精品免费一二三区| 一本在线高清不卡dvd| 亚洲日本在线a| 欧美性受xxxx黑人xyx| 三级亚洲高清视频| 精品精品国产高清一毛片一天堂| 黄网站免费久久| 国产情人综合久久777777| 波多野结衣亚洲一区| 一区二区三区成人| 日韩一卡二卡三卡四卡| 国产精品99久久久久| 中文字幕在线播放不卡一区| 在线视频你懂得一区二区三区| 亚洲va国产天堂va久久en| 精品久久久久久久久久久久久久久| 国产精品一区专区| 亚洲另类色综合网站| 日韩一区二区在线免费观看| 粉嫩一区二区三区性色av| 亚洲男人的天堂在线观看| 6080日韩午夜伦伦午夜伦| 国产成人亚洲精品青草天美| 亚洲国产中文字幕| 久久久久久一二三区| 色综合色综合色综合| 日韩成人av影视| 国产精品免费观看视频| 欧美精品一卡两卡| 成人va在线观看| 美国毛片一区二区| 中文字幕一区av| 日韩精品一区二| 欧美主播一区二区三区美女| 国产一二三精品| 亚洲成av人片在线观看无码| 国产精品蜜臀av| 欧美一级一区二区| 欧美综合在线视频| 丁香六月久久综合狠狠色| 男女视频一区二区| 亚洲一区在线看| 国产精品久久免费看| 精品久久久久久久久久久久久久久 | 国产精品久久久久毛片软件| 欧美一区二区三区免费大片| 91国偷自产一区二区开放时间| 国产精品一二三四区| 奇米一区二区三区av| 亚洲电影第三页| 亚洲视频中文字幕| 国产精品嫩草久久久久| 国产丝袜美腿一区二区三区| 日韩免费观看2025年上映的电影 | 日韩视频在线一区二区| 欧美视频中文一区二区三区在线观看| 成人app在线观看| 国产精品123区| 久久99久久精品欧美| 日韩成人av影视| 石原莉奈在线亚洲三区| 亚洲国产精品久久人人爱| 一区二区三区中文在线| 亚洲视频综合在线| 国产精品久久久一本精品| 欧美国产激情二区三区| 国产日本欧美一区二区| 国产欧美一区二区三区沐欲| 久久综合色之久久综合| 亚洲精品在线观看网站| 精品久久久影院| 精品福利一二区| 26uuu精品一区二区| 久久综合资源网| 国产亚洲va综合人人澡精品| 久久精品水蜜桃av综合天堂| 欧美激情在线一区二区三区| 国产精品白丝在线| 亚洲六月丁香色婷婷综合久久| 亚洲精品国久久99热| 亚洲电影中文字幕在线观看| 日韩一区精品视频| 久久精品久久综合| 国产乱子轮精品视频| 国产不卡高清在线观看视频| 99久久久无码国产精品| 色欧美日韩亚洲| 欧美美女bb生活片| 亚洲精品在线观看网站| 国产精品美女久久久久aⅴ| 亚洲欧美一区二区三区国产精品| 一级特黄大欧美久久久| 日韩精品国产精品| 狠狠狠色丁香婷婷综合激情 | 欧美激情在线一区二区三区| 国产精品视频观看| 亚洲电影一级片| 激情五月激情综合网| 成人黄色在线视频| 欧美日韩久久不卡| 2020日本不卡一区二区视频| 国产精品麻豆99久久久久久| 亚洲国产精品精华液网站| 激情综合色综合久久| 91亚洲男人天堂| 日韩午夜激情av| 国产精品的网站| 日韩av不卡在线观看| 丰满白嫩尤物一区二区| 在线一区二区观看| 精品捆绑美女sm三区| 亚洲精选在线视频| 国产精品一区二区三区网站| 欧美在线观看视频一区二区三区| 欧美大黄免费观看| 亚洲美女视频在线| 国产真实乱子伦精品视频| 欧美综合在线视频| 国产蜜臀av在线一区二区三区| 丝袜诱惑制服诱惑色一区在线观看| 国产乱国产乱300精品| 欧美日韩久久久一区| 国产精品麻豆视频| 久久99在线观看| 欧美性一区二区| 国产精品久久久久久久久晋中| 日韩成人一级片| 色婷婷久久久综合中文字幕| 久久综合九色综合97婷婷| 亚洲国产aⅴ成人精品无吗| 成人国产精品免费观看| 精品国产百合女同互慰| 日韩精品福利网| 欧美主播一区二区三区美女| 国产精品网友自拍| 国产精品一线二线三线精华| 91精品麻豆日日躁夜夜躁| 一区二区在线免费观看| www.日韩在线| 国产精品久久三| 国产91精品欧美| 久久精品人人做人人爽人人| 蜜臀久久久99精品久久久久久| 欧美探花视频资源| 一区二区三区在线高清| 99精品在线免费| 国产欧美一区二区在线| 国产在线播精品第三| 日韩久久久精品| 蜜臀av性久久久久蜜臀aⅴ流畅| 欧美日韩国产综合一区二区 | 在线播放日韩导航| 亚洲免费电影在线| 日本高清不卡在线观看| 亚洲人成亚洲人成在线观看图片 | 欧美精品乱码久久久久久 | 伊人色综合久久天天人手人婷| eeuss鲁片一区二区三区| 欧美—级在线免费片| www.欧美日韩| 亚洲人成网站色在线观看| 一本色道久久综合亚洲aⅴ蜜桃 | 偷拍亚洲欧洲综合| 欧美日韩一区国产| 日日夜夜免费精品视频| 日韩片之四级片| 国产一区二区三区美女| 久久久影院官网| 成人a级免费电影| 亚洲三级免费观看| 欧美日韩国产在线播放网站| 日韩电影在线观看一区| 精品播放一区二区| 成人免费高清在线| 亚洲精品亚洲人成人网在线播放| 欧美三级资源在线| 喷水一区二区三区| 国产视频一区不卡| voyeur盗摄精品| 亚洲最大成人综合| 欧美一区二区女人| 国产精品综合二区| 亚洲欧美日韩一区二区三区在线观看| 91福利社在线观看| 久久99久久久久| 日韩毛片高清在线播放| 欧美绝品在线观看成人午夜影视| 美美哒免费高清在线观看视频一区二区| 欧美成va人片在线观看| www.欧美亚洲| 日日夜夜免费精品| 欧美激情一区二区三区在线| 欧美在线视频全部完| 国产一区二区电影| 亚洲影院在线观看| 久久久99精品免费观看不卡| 日本精品一级二级| 精品一区二区成人精品|