ホームページ > ウェブフロントエンド > フロントエンドQ&A > HTML5に虫眼鏡機能を実装する方法

HTML5に虫眼鏡機能を実装する方法

藏色散人
リリース: 2023-01-28 11:01:57
オリジナル
1991 人が閲覧しました

HTML5 で虫眼鏡関数を実装する方法: 1. HTML サンプル ファイルを作成する; 2. html5 Canvas タグを使用して画像を初期化する; 3. Canvas オブジェクトと画像オブジェクトを取得する; 4. 「関数drawAnchor」を通じて() {... }」などの方法で選択範囲を拡大し、2 つの領域の中心点が一致するように元の画像上に描画します。

HTML5に虫眼鏡機能を実装する方法

このチュートリアルの動作環境: Windows 10 システム、HTML5 バージョン、DELL G3 コンピューター

虫眼鏡の実装方法html5の関数?

#【HTML5】キャンバスに虫眼鏡効果を実装しました

画像虫眼鏡

効果


#原則

最初に画像の領域を選択し、次にこの領域を拡大して、2 つの領域の中心点が一致するように元の画像上に描画します。以下の図に示すように、一貫性があります。 表示:


##Initialization

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

<img src="image.png" style="display: none" id="img">
ログイン後にコピー

Canvas オブジェクトと画像オブジェクトを取得します。ここでは

を使用します。画像をプリロードするタグ<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">var canvas = document.getElementById(&quot;canvas&quot;); var context = canvas.getContext(&quot;2d&quot;); var img = document.getElementById(&quot;img&quot;);</pre><div class="contentsignin">ログイン後にコピー</div></div>関連変数の設定

// 图片被放大区域的中心点,也是放大镜的中心点
var centerPoint = {};
// 图片被放大区域的半径
var originalRadius = 100;
// 图片被放大区域
var originalRectangle = {};
// 放大倍数
var scale = 2;
// 放大后区域
var scaleGlassRectangle
ログイン後にコピー

背景画像を描画

function drawBackGround() {
    context.drawImage(img, 0, 0);
}
ログイン後にコピー

画像を拡大する範囲を計算

ここでは、マウスの位置を拡大領域の中心点として使用します (虫眼鏡はマウスの移動に合わせて移動します)。これは、キャンバスが絵を描くときに左上隅の座標と領域の幅と高さを知る必要があるためです。 , そのため、ここでは領域の範囲を計算します

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 stylelineWidth などのキャンバスのコンテキスト属性を含む現在のキャンバスの状態を保存し、この状態をプッシュします。スタック。 restore は、最後に保存した状態を復元し、スタックから最上位の状態をポップするために使用されます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">context.save(); context.beginPath(); context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false); context.clip(); ...... context.restore();</pre><div class="contentsignin">ログイン後にコピー</div></div>虫眼鏡領域の計算

領域の左上隅の座標と、中心点を通る領域の幅と高さ、拡大された領域の幅と高さを取得します。 、倍率。

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

メソッドを使用します。キャンバス自体を絵として扱い、拡大された領域の画像を虫眼鏡領域に描画します。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">context.drawImage(canvas, originalRectangle.x, originalRectangle.y, originalRectangle.width, originalRectangle.height, scaleGlassRectangle.x, scaleGlassRectangle.y, scaleGlassRectangle.width, scaleGlassRectangle.height );</pre><div class="contentsignin">ログイン後にコピー</div></div>拡大されたエッジを描画します

createRadialGradient

グラデーション画像を描画するために使用されます<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">context.beginPath(); var gradient = context.createRadialGradient( centerPoint.x, centerPoint.y, originalRadius - 5, centerPoint.x, centerPoint.y, originalRadius); gradient.addColorStop(0, &amp;#39;rgba(0,0,0,0.2)&amp;#39;); gradient.addColorStop(0.80, &amp;#39;silver&amp;#39;); gradient.addColorStop(0.90, &amp;#39;silver&amp;#39;); gradient.addColorStop(1.0, &amp;#39;rgba(150,150,150,0.9)&amp;#39;); context.strokeStyle = gradient; context.lineWidth = 5; context.arc(centerPoint.x, centerPoint.y, originalRadius, 0, Math.PI * 2, false); context.stroke();</pre><div class="contentsignin">ログイン後にコピー</div></div>マウス イベントを追加

マウス移動イベントを追加しますCanvas

canvas.onmousemove = function (e) {
    ......
}
ログイン後にコピー

座標の変換

マウス イベントによって取得される座標は通常、画面またはウィンドウの座標であるため、キャンバスの座標に変換する必要があります。

getBoundingClientRect

は、ブラウザ ウィンドウを基準としたページ上の要素の左、上、右、下の位置を取得するために使用されます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false;">function windowToCanvas(x, y) { var bbox = canvas.getBoundingClientRect(); return {x: x - bbox.left, y: y - bbox.top} }</pre><div class="contentsignin">ログイン後にコピー</div></div>マウス スタイルの変更

CSS を通じてマウス スタイルを変更できます

#canvas {
    display: block;
    border: 1px solid red;
    margin: 0 auto;
    cursor: crosshair;
}
ログイン後にコピー

グラフ虫眼鏡

キャンバスに基づいていくつかのグラフや画像を描画する場合があります。 if 2 つの要素の座標が比較的近いため、要素の選択に影響します。たとえば、2 本の線を描画すると、1 本の線の座標は

(200.5, 400) -> (200.5, 200)

、もう一方の線の座標は (201.5, 400) -> (201.5, 20) である場合、次の図に示すように、2 つの線はほぼ重なり合います。
#チャート虫眼鏡を使用する効果


原則

地図の凡例と同様、虫眼鏡でも以下の図に示すように、より正確な凡例が表示されます。 :


虫眼鏡座標系では、以下の図に示すように、元の領域が大きくなります。

#

绘制原始线段

首先创建一个线段对象

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, &#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();
}
ログイン後にコピー

添加事件

鼠标拖动

鼠标移动到放大镜上,然后按下鼠标左键,可以拖动放大镜,不按鼠标左键或者不在放大镜区域都不可以拖动放大镜。
为了实现上面的效果,我们要实现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 == &#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();
}
ログイン後にコピー
推荐学习:《HTML5视频教程》  

以上がHTML5に虫眼鏡機能を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート