如何创建类似于polyvore提供的裁剪功能

时间:2015-05-15 03:54:09

标签: javascript jquery-plugins

如何在类似polyvore.com提供的功能的图像上提供裁剪功能,其中包含以下屏幕截图。

enter image description here

enter image description here

4 个答案:

答案 0 :(得分:4)

  • 这不是插件。事实上,似乎根本没有 JQuery

  • 开发人员似乎复制了 FB Toolkit (图片裁剪)的未曝光部分,并复制了部分 Handle-Bars.JS

    < / LI>
  • 动画使用 SVG

  • 完成

主JS工作文件(30289行未缩小)是:

http://akwww.polyvorecdn.com/rsrc/montage-4d3d377ea56d496ebf373692dc2cfe53.js

您最感兴趣的部分是:

ImageItem.prototype.startCrop = function() {
    LassoDialog.showExpanded(this)
};

开发人员从FB的源代码中抓取了这个并略微修改了它:

function FBPhoto(b) {
    this.fbImgUrl = b.imgurl;
    this.pid = b.pid;
    FBPhoto.superclass.constructor.call(this, b);
    var a = 3;
    Event.addListener(this.img, "error", function() {
        a--;
        if (a) {
            this.img.setSrc("");
            window.setTimeout(Event.wrapper(function() {
                this.updateImage()
            }, this), 200)
        }
    }, this);
    if (!this.rect.width()) {
        getNaturalWidthHeight(b.imgurl, Event.wrapper(function(c, d) {
            if (c && d) {
                b.w = c;
                b.h = d
            } else {
                b.w = 200;
                b.h = 200
            }
            b.x = 0;
            b.y = 0;
            this.rect = new Rect(-b.w / 2, -b.h / 2, b.w / 2, b.h / 2);
            this.translation = new Point(b.x + b.w / 2, b.y + b.h / 2);
            Event.trigger(this, "change");
            Event.trigger(this, "sized", this)
        }, this))
    }
}

然后扩展方法:

extend(FBPhoto, ImageItem);
FBPhoto.mapImgUrl = function(a, b) {
    var d = UI.sizeMap[b].dim;
    var c;
    if (d < 100) {
        c = "t"
    } else {
        if (d < 150) {
            c = "s"
        } else {
        }
    }
    if (c) {
        a = a.replace(/_n\.jpg/, "_" + c + ".jpg").replace(/\/n([^\/]*)\.jpg$/, "/" + c + "$1.jpg")
    }
    return a
};
FBPhoto.prototype.startCrop = function() {
    LassoDialog.showSimple(imgUrl, this, {header: loc("Crop your friend's face by drawing a path around it..."),onSuccess: Event.wrapper(function(b, a) {
            this.mask_spec = b || [];
            this.updateImage();
            Event.trigger(this, "updateactions", this);
            this.setDimensions(a);
            Event.trigger(this, "change")
        }, this)})
};

答案 1 :(得分:2)

确定必要的功能

我一直在寻找的功能:

  1. 应该允许覆盖图像
  2. 应该允许编辑各个点
  3. 应该可以生成裁剪的图像
  4. 理想情况下,它应该允许灰色显示图像的非裁剪区域
  5. 可悲的是(有点令人惊讶)我找不到为你做这个的图书馆,但我得到的最接近的是netplayer crop图书馆。在之前的4个点中,它只能执行第1点和第3点。换句话说,有必要自行解决方案,因为我认为第2点是一个非常大的要求。接下来的两节将为您完成一些工作,但它绝对不同于现成的插件。

    绘制可编辑多边形

    我能找到的用于绘制多边形的最佳库是PolyK.js。遗憾的是,它远非完美,但它确实极大地简化了这一过程。

    您可以在下面找到一个基本的可编辑多边形,取自PolyK.js文档。

    var stage, s, dragged;
    var poly = [93, 195, 129, 92, 280, 81, 402, 134, 477, 70, 619, 61, 759, 97, 758, 247, 662, 347, 665, 230, 721, 140, 607, 117, 472, 171, 580, 178, 603, 257, 605, 377, 690, 404, 787, 328, 786, 480, 617, 510, 611, 439, 544, 400, 529, 291, 509, 218, 400, 358, 489, 402, 425, 479, 268, 464, 341, 338, 393, 427, 373, 284, 429, 197, 301, 150, 296, 245, 252, 384, 118, 360, 190, 272, 244, 165, 81, 259, 40, 216];
    var dots = [];
    
    function Go() {
      stage = new Stage("c");
      s = new Sprite();
      stage.addChild(s);
    
      for (var i = 0; i < poly.length / 2; i++) {
        var dot = new Dot();
        dot.x = poly[2 * i];
        dot.y = poly[2 * i + 1];
        dots.push(dot);
        dot.addEventListener(MouseEvent.MOUSE_DOWN, onMD);
        stage.addChild(dot);
      }
      stage.addEventListener(MouseEvent.MOUSE_MOVE, onMM);
      stage.addEventListener(MouseEvent.MOUSE_UP, onMU);
      redraw();
    }
    
    function onMD(e) {
      dragged = e.target;
    }
    
    function onMU(e) {
      dragged = null;
    }
    
    function onMM(e) {
      if (dragged != null) {
        dragged.x = stage.mouseX;
        dragged.y = stage.mouseY;
        var i = dots.indexOf(dragged);
        poly[2 * i] = stage.mouseX;
        poly[2 * i + 1] = stage.mouseY;
        redraw();
      }
    }
    
    function redraw() {
      s.graphics.clear();
      fillPoly(poly, s, 0x00bbff);
    }
    
    
    function strokePoly(poly, s) {
      var n = poly.length >> 1;
      s.graphics.lineStyle(6, 0xff0000);
      s.graphics.moveTo(poly[0], poly[1]);
      for (var i = 1; i < n; i++) s.graphics.lineTo(poly[2 * i], poly[2 * i + 1]);
      s.graphics.lineTo(poly[0], poly[1]);
    }
    
    function fillPoly(poly, s, color) {
      var tgs = PolyK.Triangulate(poly);
      s.graphics.beginFill(color);
      s.graphics.drawTriangles(poly, tgs);
    }
    
    function drawTgs(vrt, ind, s) {
      var n = ind.length / 3;
    
      s.graphics.lineStyle(1, 0x000000);
    
      for (var i = 0; i < n; i++) {
        var i0 = ind[3 * i];
        var i1 = ind[3 * i + 1];
        var i2 = ind[3 * i + 2]
        s.graphics.moveTo(vrt[2 * i0], vrt[2 * i0 + 1]);
        s.graphics.lineTo(vrt[2 * i1], vrt[2 * i1 + 1]);
        s.graphics.lineTo(vrt[2 * i2], vrt[2 * i2 + 1]);
        s.graphics.lineTo(vrt[2 * i0], vrt[2 * i0 + 1]);
      }
    
    }
    
    function Dot() {
      Sprite.apply(this); // inherits from Sprite
      this.graphics.beginFill(0x000000, 0.15);
      this.graphics.drawCircle(0, 0, 13);
      this.graphics.beginFill(0xffffff, 1.0);
      this.graphics.drawCircle(0, 0, 6);
      this.buttonMode = true;
    }
    Dot.prototype = new Sprite();
    
    document.addEventListener("DOMContentLoaded", Go);
    <script src="http://lib.ivank.net/ivank.js"></script>
    <script src="http://polyk.ivank.net/polyk.js"></script>
    
    <canvas id="c"></canvas>

    为此,我们需要添加添加点和删除点的功能。我实现了这一点,任何地方的任何点击都会在多边形的最近部分附近添加点,并且通过单击它们而不拖动来完成移除点。另外,我添加了<canvas>下的图片,只是为了了解结果(在整页模式下打开片段以获得一个好主意)。

    var stage, s, dragged;
    var poly = [77, 222, 81, 187, 112, 195, 143, 183, 150, 222, 133, 262, 95, 258];
    var dots = [];
    var originalPosition = {
      x: 0,
      y: 0
    };
    
    var Go = function() {
      stage = new Stage("c");
      s = new Sprite();
      stage.addChild(s);
    
      stage.addEventListener(MouseEvent.MOUSE_UP, removeOrAddDots);
    
      for (var i = 0; i < poly.length / 2; i++) {
        var dot = new Dot();
        dot.x = poly[2 * i];
        dot.y = poly[2 * i + 1];
        dots.push(dot);
        dot.addEventListener(MouseEvent.MOUSE_DOWN, clickDot);
        stage.addChild(dot);
      }
      stage.addEventListener(MouseEvent.MOUSE_MOVE, dragDot);
      stage.addEventListener(MouseEvent.MOUSE_UP, releaseDot);
      redraw();
    }
    
    var clickDot = function(e) {
      dragged = e.target;
      originalPosition.x = dragged.x;
      originalPosition.y = dragged.y;
    }
    
    var releaseDot = function(e) {
      if (dragged && Math.abs(originalPosition.x - dragged.x) < 2 && Math.abs(originalPosition.y - dragged.y) < 2) {
        stage.removeChild(dragged);
        var index = dots.indexOf(dragged);
        poly.splice(index * 2, 2);
        dots.splice(index, 1);
        redraw();
      }
      dragged = null;
    }
    
    var dragDot = function(e) {
      if (dragged != null) {
        dragged.x = stage.mouseX;
        dragged.y = stage.mouseY;
        var i = dots.indexOf(dragged);
        poly[2 * i] = stage.mouseX;
        poly[2 * i + 1] = stage.mouseY;
        redraw();
      }
    }
    
    var removeOrAddDots = function(ev) {
      if (dragged) {
        //ignore, because we're dragging a point
      } else {
        var isc = PolyK.ClosestEdge(poly, stage.mouseX, stage.mouseY);
        var dot = new Dot();
        dot.x = stage.mouseX;
        dot.y = stage.mouseY;
        dots.splice((isc.edge + 1), 0, dot);
        poly.splice((isc.edge + 1) * 2, 0, dot.x);
        poly.splice((isc.edge + 1) * 2 + 1, 0, dot.y);
        stage.addChild(dot);
        dot.addEventListener(MouseEvent.MOUSE_DOWN, clickDot);
        redraw();
      }
    }
    
    var redraw = function() {
      s.graphics.clear();
      fillPoly(poly, s, 0x00bbff);
    }
    
    
    var strokePoly = function(poly, s) {
      var n = poly.length >> 1;
      s.graphics.lineStyle(6, 0xff0000);
      s.graphics.moveTo(poly[0], poly[1]);
      for (var i = 1; i < n; i++) s.graphics.lineTo(poly[2 * i], poly[2 * i + 1]);
      s.graphics.lineTo(poly[0], poly[1]);
    }
    
    var fillPoly = function(poly, s, color) {
      var tgs = PolyK.Triangulate(poly);
      s.graphics.beginFill(color, .7);
      s.graphics.drawTriangles(poly, tgs);
    }
    
    function Dot() {
      Sprite.apply(this); // inherits from Sprite
      this.graphics.beginFill(0x000000, 0.15);
      this.graphics.drawCircle(0, 0, 13);
      this.graphics.beginFill(0xffffff, 1.0);
      this.graphics.drawCircle(0, 0, 6);
      this.buttonMode = true;
    }
    Dot.prototype = new Sprite();
    
    document.addEventListener("DOMContentLoaded", Go);
    canvas {
      position: absolute;
      left: 0px;
      top: 0px;
    }
    <script src="http://lib.ivank.net/ivank.js"></script>
    <script src="http://polyk.ivank.net/polyk.js"></script>
    
    <img src="http://i.stack.imgur.com/eNvlM.png">
    <canvas id="c"></canvas>

    裁剪

    现在我们有了一个多边形(poly中的点数组),我们可以使用你已经使用的任何服务器端语言简单地裁掉多边形之外的任何区域,here是一些关于如何使用PHP的文档(或者它可以在客户端上完成,就像我之前提到的netplayer crop库中所做的那样)。无论哪种方式,这都应该相对简单。或者您可以完全跳过它并使用像polyClip.js这样的库,只要您加载图像就可以在运行时执行(只有在我们讨论的是JPG时才建议)。

答案 2 :(得分:0)

具有React扩展名的React.js可能就是你所追求的。从你的照片来看,这可以解决你想要的问题。

用于拖动事件(拖动部分) http://jsfiddle.net/mattpodwysocki/pfCqq/

用于鼠标事件(裁剪部分) http://jsfiddle.net/mattpodwysocki/gJtjx/

<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.1.18/rx.js"></script>

包含脚本后,您可以入侵代码......

React.js:用于构建用户界面的JAVASCRIPT库 https://facebook.github.io/react/

React extensions:让您轻松处理事件,例如点击事件,键盘事件,拖放事件等等 https://github.com/Reactive-Extensions/RxJS/tree/master/examples

答案 3 :(得分:-1)

这不是100%,但从它的外观来看,它正在使用FabricJS