【基础知识】HTML5 Canvas 项目橡皮筋选框局部放大器(图文)

我的处女作《Canvas系列教程》在我的Github上正在连载更新,希望能得到您的关注和支持,让我有更多的动力进行创作。

教程介绍、教程目录等能在README里查阅。

传送门:https://github.com/827652549/CanvasStudy

介绍

Canvas橡皮筋选框局部放大器,是利用Canvas技术:拖拽鼠标创建选区,松开鼠标后自动放大选区的图像。

演示链接

https://827652549.github.io/Canvas/Unit1/RubberBands.html

效果图

核心思路

  1. 实现橡皮筋选框DIV,实现隐藏、显示、属性设置、属性调整等功能
  2. 基于Canvas和鼠标移动时的event,调整拖拽时橡皮筋选框DIV的绝对位置和属性
  3. 使用drawIamge()实现Canvas的局部放大功能

详细过程

相关方法介绍已经注释在代码中

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>橡皮筋选框放大器</title>
    <style>
        body {
            background: rgba(100, 145, 250, 0.3);
        }

        #canvas {
            margin-left: 20px;
            margin-right: 0;
            margin-bottom: 20px;
            border: thin solid #aaaaaa;
            /*十字瞄准线*/
            cursor: crosshair;
            padding: 0;
        }

        #controls {
            margin: 20px 0px 20px 20px;
        }

        #rubberbandDiv {
            /*绝对定位,方便位置选取*/
            position: absolute;
            border: 3px solid yellow;
            cursor: crosshair;
            display: none;
        }
    </style>
</head>
<body>
<!--控制重置画面的按钮-->
<div id="controls">
    <input type="button" id="resetButton" value="Reset">
</div>
<!--橡皮筋选取狂div-->
<div id="rubberbandDiv"></div>
<canvas id="canvas" width="800" height="520">Canvas not supported</canvas>
<p>拖拽鼠标拉取橡皮筋,选中区域并放大</p>
</body>
<script>
    var canvas = document.getElementById('canvas'),
        context = canvas.getContext('2d'),
        rubberbandDiv = document.getElementById('rubberbandDiv'),
        resetButton = document.getElementById('resetButton'),
        image = new Image(),
        //鼠标按下时刻的对象
        mousedown = {},
        //橡皮筋矩形对象
        rubberbandRectangle = {},
        dragging = false;

    //Functions……

    /**
     * 将#rubberbandDiv的左上角移动到鼠标按下的位置
     * @param x
     * @param y
     */
    function rubberbandStart(x, y) {
        mousedown.x = x;
        mousedown.y = y;

        rubberbandRectangle.left = mousedown.x;
        rubberbandRectangle.top = mousedown.y;

        moveRubberbandDiv();
        showRubberbandDiv();

        dragging = true;
    }

    /**
     * 对橡皮筋选取框进行移动和缩放
     * @param x
     * @param y
     */
    function rubberbandStretch(x, y) {
        //「左上」「右下」「左下」「右上」的各种两两组合的拉伸方式
        rubberbandRectangle.left = x < mousedown.x ? x : mousedown.x;
        rubberbandRectangle.top = y < mousedown.y ? y : mousedown.y;

        rubberbandRectangle.width = Math.abs(x - mousedown.x);
        rubberbandRectangle.height = Math.abs(y - mousedown.y);

        moveRubberbandDiv();
        resizeRubberbandDiv();
    };

    /**
     * 将选中的区域放大并绘制,并将橡皮筋div隐藏
     */
    function rubberbandEnd() {
        //返回涵盖元素的大小以及窗口位置的对象
        var bbox = canvas.getBoundingClientRect();

        try {
            //选区放大
            context.drawImage(
                canvas,
                rubberbandRectangle.left - bbox.left,
                rubberbandRectangle.top - bbox.top,
                rubberbandRectangle.width,
                rubberbandRectangle.height,
                0, 0, canvas.width, canvas.height
            );
        } catch (e) {
            // suppress error message when mouse is released
            // outside the canvas
            alert('鼠标释放错误警报!');
        }

        resetRubberbandRectangle();

        rubberbandDiv.style.width = 0;
        rubberbandDiv.style.height = 0;

        hideRubberbandDiv();

        dragging = false;

    }


    /**
     * 让橡皮筋选狂的属性和橡皮筋矩形对象的位置保持一致
     */
    function moveRubberbandDiv() {
        rubberbandDiv.style.top = rubberbandRectangle.top + 'px';
        rubberbandDiv.style.left = rubberbandRectangle.left + 'px';
    }

    /**
     * 调整橡皮筋div的宽高
     */
    function resizeRubberbandDiv() {
        rubberbandDiv.style.width = rubberbandRectangle.width + 'px';
        rubberbandDiv.style.height = rubberbandRectangle.height + 'px';
    }

    /**
     * 通过display显示橡皮筋
     */
    function showRubberbandDiv() {
        rubberbandDiv.style.display = 'inline';
    }

    /**
     * 通过display隐藏橡皮筋
     */
    function hideRubberbandDiv() {
        rubberbandDiv.style.display = 'none';
    }

    /**
     * 重置初始化橡皮筋矩形对象
     */
    function resetRubberbandRectangle() {
        rubberbandRectangle = {top: 0, left: 0, width: 0, height: 0};
    }

    //Event handlers……

    canvas.onmousedown = function (ev) {
        var x = ev.x || ev.clientX,
            y = ev.y || ev.clientY;

        ev.preventDefault();
        rubberbandStart(x, y);
    };

    window.onmousemove = function (ev) {
        var x = ev.x || ev.clientX,
            y = ev.y || ev.clientY;

        ev.preventDefault();
        if (dragging) {
            rubberbandStretch(x, y);
        }
    };

    window.onmouseup = function (ev) {
        ev.preventDefault();
        rubberbandEnd();
    };

    image.onload = function (ev) {
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
    };

    resetButton.onclick=function (ev) {
        context.clearRect(0,0,context.canvas.width,context.canvas.height);
        context.drawImage(image,0,0,canvas.width,canvas.height);
    };

    //Initialization……

    image.src='../images/arch.png';
</script>
</html>

小结

  1. drawImage()方法是处理Canvas局部裁剪的核心。
  2. 要考虑阻止默认事件的发生。
  3. 选框拖拽时要考虑多种情况,如选框可能从左上到右下方向,也可能右下到左上方向。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值