Rumah > hujung hadapan web > Soal Jawab bahagian hadapan > Bagaimana untuk melaksanakan fungsi kaca pembesar dalam html5

Bagaimana untuk melaksanakan fungsi kaca pembesar dalam html5

藏色散人
Lepaskan: 2023-01-28 11:01:57
asal
2004 orang telah melayarinya

Cara melaksanakan fungsi kaca pembesar dalam HTML5: 1. Buat fail sampel HTML 2. Mulakan imej menggunakan tag kanvas html5 3. Dapatkan kanvas dan objek imej; () {... }" dan kaedah lain untuk membesarkan kawasan yang dipilih, dan kemudian melukisnya pada gambar asal, memastikan titik tengah kedua-dua kawasan adalah konsisten.

Bagaimana untuk melaksanakan fungsi kaca pembesar dalam html5

Persekitaran pengendalian tutorial ini: sistem Windows 10, versi HTML5, komputer DELL G3

Cara melaksanakan kaca pembesar fungsi dalam html5?

【HTML5】Kanvas melaksanakan kesan kaca pembesar

Kanta pembesar gambar

Kesan


Prinsip

Mula-mula pilih kawasan gambar, kemudian besarkan kawasan ini, dan kemudian lukiskannya pada gambar asal untuk memastikan titik tengah dua kawasan adalah konsisten, seperti yang ditunjukkan dalam rajah di bawah Paparan:

Mulakan

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

<img src="image.png" style="display: none" id="img">
Salin selepas log masuk

untuk mendapatkan kanvas dan objek imej, di sini gunakan teg <img> untuk pramuat imej

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var img = document.getElementById("img");
Salin selepas log masuk

tetapan berkaitan Pembolehubah

// 图片被放大区域的中心点,也是放大镜的中心点
var centerPoint = {};
// 图片被放大区域的半径
var originalRadius = 100;
// 图片被放大区域
var originalRectangle = {};
// 放大倍数
var scale = 2;
// 放大后区域
var scaleGlassRectangle
Salin selepas log masuk

Lukis imej latar belakang

function drawBackGround() {
    context.drawImage(img, 0, 0);
}
Salin selepas log masuk

Kira julat kawasan di mana imej itu dibesarkan

Di sini kita menggunakan kedudukan tetikus sebagai titik tengah kawasan yang diperbesarkan ( Kaca pembesar bergerak semasa tetikus bergerak), kerana kanvas perlu mengetahui koordinat sudut kiri atas dan lebar dan ketinggian kawasan apabila melukis gambar, jadi di sini kita mengira julat kawasan

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

Lukiskan kawasan kaca pembesar

Kawasan tanaman

Kanta pembesar biasanya berbentuk bulat gunakan fungsi clip untuk memangkas kawasan bulat, dan kemudian lukis imej yang dibesarkan di kawasan ini. Sebaik sahaja kawasan tertentu dipotong, semua lukisan masa hadapan akan dihadkan kepada kawasan ini Di sini kami menggunakan kaedah save dan restore untuk membersihkan pengaruh kawasan yang dipotong. save menyimpan keadaan kanvas semasa, termasuk atribut konteks kanvas, seperti style, lineWidth, dsb., dan kemudian menolak keadaan ini ke dalam tindanan. restore Digunakan untuk memulihkan keadaan simpanan terakhir dan mengeluarkan keadaan paling teratas daripada timbunan.

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

Kira kawasan kaca pembesar

Dapatkan koordinat penjuru kiri atas kawasan dan lebar dan tinggi kawasan melalui titik tengah, lebar dan ketinggian kawasan pembesaran dan faktor pembesaran.

scaleGlassRectangle = {
    x: centerPoint.x - originalRectangle.width * scale / 2,
    y: centerPoint.y - originalRectangle.height * scale / 2,
    width: originalRectangle.width * scale,
    height: originalRectangle.height * scale
}
Salin selepas log masuk

Lukis gambar

Di sini kita menggunakan kaedah context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height); untuk menggunakan kanvas itu sendiri sebagai gambar, kemudian ambil imej kawasan yang dibesarkan dan lukiskannya ke dalam kaca pembesar kawasan.

context.drawImage(canvas,
    originalRectangle.x, originalRectangle.y,
    originalRectangle.width, originalRectangle.height,
    scaleGlassRectangle.x, scaleGlassRectangle.y,
    scaleGlassRectangle.width, scaleGlassRectangle.height
);
Salin selepas log masuk

Lukis tepi yang diperbesarkan

createRadialGradient Digunakan untuk melukis imej kecerunan

context.beginPath();
var gradient = context.createRadialGradient(
    centerPoint.x, centerPoint.y, originalRadius - 5,
    centerPoint.x, centerPoint.y, originalRadius);
gradient.addColorStop(0, &#39;rgba(0,0,0,0.2)&#39;);
gradient.addColorStop(0.80, &#39;silver&#39;);
gradient.addColorStop(0.90, &#39;silver&#39;);
gradient.addColorStop(1.0, &#39;rgba(150,150,150,0.9)&#39;);

context.strokeStyle = gradient;
context.lineWidth = 5;
context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false);
context.stroke();
Salin selepas log masuk

Tambah acara tetikus

Tambahkan acara pergerakan tetikus ke kanvas

canvas.onmousemove = function (e) {
    ......
}
Salin selepas log masuk

Tukar koordinat

Koordinat yang diperolehi oleh peristiwa tetikus secara amnya ialah koordinat skrin atau tetingkap dan kita perlu menukarnya kepada koordinat kanvas. getBoundingClientRect digunakan untuk mendapatkan kedudukan kiri, atas, kanan dan bawah elemen pada halaman berbanding tetingkap penyemak imbas.

function windowToCanvas(x, y) {
    var bbox = canvas.getBoundingClientRect();
    return {x: x - bbox.left, y: y - bbox.top}
}
Salin selepas log masuk

Ubah suai gaya tetikus

Kami boleh mengubah suai gaya tetikus melalui css

#canvas {
    display: block;
    border: 1px solid red;
    margin: 0 auto;
    cursor: crosshair;
}
Salin selepas log masuk

Kanta pembesar carta

Kami mungkin melukis beberapa carta berdasarkan kanvas Atau imej, jika koordinat dua elemen adalah agak rapat, ia akan memberi sedikit kesan kepada pemilihan elemen Sebagai contoh, jika kita melukis dua garis, koordinat satu garis adalah (200.5, 400) -> (200.5, 200) dan koordinat garis yang satu lagi. adalah (201.5, 400) -> (201.5, 20) , maka kedua-dua garisan akan hampir bertindih, seperti yang ditunjukkan dalam rajah di bawah:

Kesan penggunaan kaca pembesar carta

Prinsip

Sama seperti legenda dalam peta, kaca pembesar menggunakan legenda yang lebih tepat, seperti yang ditunjukkan di bawah:

Dalam sistem koordinat kaca pembesar, kawasan asal akan menjadi lebih besar, seperti yang ditunjukkan di bawah Ditunjukkan

绘制原始线段

首先创建一个线段对象

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;
}
Salin selepas log masuk

初始化线段

// 原始线段
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;
    }
}
Salin selepas log masuk

绘制线段

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();
    }
}
Salin selepas log masuk

计算原始区域和放大镜区域

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);
}
Salin selepas log masuk

计算线段在新坐标系统的位置

由原理图我们知道,放大镜中使用坐标系的图例要比原始坐标系更加精确,比如原始坐标系使用 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;
}
Salin selepas log masuk

绘制放大镜中心点

绘制放大镜中心的瞄准器

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();
}
Salin selepas log masuk

绘制放大镜

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, &#39;silver&#39;);
    gradient.addColorStop(0.90, &#39;silver&#39;);
    gradient.addColorStop(1, &#39;black&#39;);
    context.strokeStyle = gradient;
    context.lineWidth = 5;
    context.arc(parseInt(centerPoint.x), parseInt(centerPoint.y), originalRadius, 0, Math.PI * 2, false);
    context.stroke();

    drawAnchor();
}
Salin selepas log masuk

添加事件

鼠标拖动

鼠标移动到放大镜上,然后按下鼠标左键,可以拖动放大镜,不按鼠标左键或者不在放大镜区域都不可以拖动放大镜。
为了实现上面的效果,我们要实现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;
}
Salin selepas log masuk

鼠标双击

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

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();
}
Salin selepas log masuk

键盘事件

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

document.onkeyup = function (e) {
    if (e.key == &#39;w&#39;) {
        centerPoint.y = intAdd(centerPoint.y, -0.2);
    }
    if (e.key == &#39;a&#39;) {
        centerPoint.x = intAdd(centerPoint.x, -0.2);
    }
    if (e.key == &#39;s&#39;) {
        centerPoint.y = intAdd(centerPoint.y, 0.2);
    }
    if (e.key == &#39;d&#39;) {
        centerPoint.x = intAdd(centerPoint.x, 0.2);
    }
    draw();
}
Salin selepas log masuk
推荐学习:《HTML5视频教程》  

Atas ialah kandungan terperinci Bagaimana untuk melaksanakan fungsi kaca pembesar dalam html5. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan