HTML5 photoshop喜欢多边形套索选择

时间:2012-04-12 07:52:15

标签: javascript jquery html5-canvas

我希望通过让用户创建一个封闭的形状来构建一个工具来剪切一部分照片。用户应该能够开始绘制线条。从a点到b点,再到c,e,d,e,f ....最终再次指向a闭合形状。

我想使用HTML5画布。我认为这可能是一个很好的选择,我正在考虑使用像flashcanvas这样的东西作为IE /旧浏览器的后备?

是否有任何教程/开源应用程序可以用来构建这类东西? 这是我第一次使用HTML5画布构建应用程序,所以我是否应该担心任何陷阱?

2 个答案:

答案 0 :(得分:4)

我认为这是画布的高级用法。您必须了解基础知识,如何绘制,如何使用图层,如何操作像素。只需向谷歌索取教程。

假设您了解之前的内容,我会尝试一下。我之前从未这样做,但我有一个想法:

你需要3个画布:

  • 包含图片的图片(图片大小)
  • 用户绘制选择形状的图层(图片的大小,在第一个画布的顶部)
  • 结果画布,将包含您的裁剪图片(相同尺寸,此图片不需要显示)

当用户点击你的图片时:实际上,他点击图层,图层被清除并开始换行。

当他再次点击它时,会绘制上一个开始的行,另一个开始,等等......你一直这样做,直到你点击一个非空白像素(这意味着你关闭了形状)。

如果您希望用户预览线条,则需要另一个画布(在此处说明http://dev.opera.com/articles/view/html5-canvas-painting/#line

当形状关闭时,用户必须在形状内部或外部单击以确定要选择的部分。例如,您使用半透明灰色填充该部分(此处说明了洪水填充http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/

现在图层画布包含与用户选择对应的彩色形状。

从图层获取像素数据并读取数组,每次在索引 i 处找到非空白像素时,将此像素从主画布复制到结果画布:< / p>

/* First, get pixel data from your 3 canvas into 
 * layerPixData, resultPixData, picturePixData 
*/

// read the entire pixel array
for (var i = 0 ; i < layerPixData.length ; i+=4 ) {
    //if the pixel is not blank, ie. it is part of the selected shape
    if ( layerPixData[i] != 255 || layerPixData[i+1]  != 255 || layerPixData[i+2] != 255 ) {
        // copy the data of the picture to the result
        resultPixData[i] = picturePixData[i]; //red
        resultPixData[i+1] = picturePixData[i+1]; //green
        resultPixData[i+2] = picturePixData[i+2]; //blue
        resultPixData[i+3] = picturePixData[i+3]; //alpha

        // here you can put the pixels of your picture to white if you want

    }

}

如果您不知道像素操作的工作原理,请阅读此https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas

然后,使用putImageData将像素绘制到结果画布。任务完成 !

如果您想移动选择的行,请前往:http://simonsarris.com/blog/225-canvas-selecting-resizing-shape

答案 1 :(得分:1)

您应该如何做到这一点: 下面的代码在页面顶部添加了一个画布,然后通过单击并拖动,将突出显示选择区域。之后您需要做的是从底层页面制作屏幕截图,并在画布中创建图像中的遮罩层,并将其应用于屏幕截图,就像在其他答案中显示它一样。

/* sample css code for the canvas
#overlay-canvas {
    position: absolute;
    top: 0;
    left: 0;
    background-color: transparent;
    opacity: 0.4;
    -moz-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    -o-user-select: none;
}
*/

function getHighIndex(selector) {
    if (!selector) { selector = "*" };

    var elements = document.querySelectorAll(selector) ||
                   oXmlDom.documentElement.selectNodes(selector);
    var ret = 0;

    for (var i = 0; i < elements.length; ++i) {
        if (deepCss(elements[i],"position") === "static")
            continue;

        var temp = deepCss(elements[i], "z-index");

        if (temp != "auto")
            temp = parseInt(temp, 10) || 0;
        else
            continue;

        if (temp > ret)
            ret = temp;
    }
    return ret;
}

maxZIndex = getHighIndex();

$.fn.extend({
    lasso: function () {
        return this
        .mousedown(function (e) {
            // left mouse down switches on "capturing mode"
            if (e.which === 1 && !$(this).is(".lassoRunning")) {
                var point = [e.offsetX, e.offsetY];
                $(this).addClass("lassoRunning");
                $(this).data("lassoPoints", [point]);
                $(this).trigger("lassoStart", [point]);
            }
        })
        .mouseup(function (e) {
            // left mouse up ends "capturing mode" + triggers "Done" event
            if (e.which === 1 && $(this).is(".lassoRunning")) {
                $(this).removeClass("lassoRunning");
                $(this).trigger("lassoDone", [$(this).data("lassoPoints")]);
            }
        })
        .mousemove(function (e) {
            // mouse move captures co-ordinates + triggers "Point" event
            if ($(this).is(".lassoRunning")) {
                var point = [e.offsetX, e.offsetY];
                $(this).data("lassoPoints").push(point);
                $(this).trigger("lassoPoint", [point]);
            }
        });
    }
});


function onLassoSelect() {
    // creating canvas for lasso selection
    var _canvas = document.createElement('canvas');
    _canvas.setAttribute("id", "overlay-canvas");
    _canvas.style.zIndex = ++maxZIndex;
    _canvas.width = document.width
    _canvas.height = document.height
    document.body.appendChild(_canvas);
    ctx = _canvas.getContext('2d'),
    ctx.strokeStyle = '#0000FF';
    ctx.lineWidth = 5;

    $(_canvas)
        .lasso()

        .on("lassoStart", function(e, lassoPoint) {
            console.log('lasso start');

            var pos = lassoPoint;
            ctx.beginPath();
            ctx.moveTo(pos[0], pos[1]);
            console.log(pos);
        })

        .on("lassoDone", function(e, lassoPoints) {
            console.log('lasso done');

            var pos = lassoPoints[0];
            ctx.lineTo(pos[0], pos[1]);
            ctx.fill();
            console.log(pos);
        })

        .bind("lassoPoint", function(e, lassoPoint) {
            var pos = lassoPoint;
            ctx.lineTo(pos[0], pos[1]);
            ctx.fill();
            console.log(pos);
        });
}