>source

디자이너 기능을 사용하여 구현하고 있습니다.패브릭 JS 내 편에 내 아이디어는 패브릭의 setBackgroundImage를 사용하여 배경 이미지를 설정하는 것입니다. 또한 크기와 위치를 가져 와서 투명한 사각형의 특정 영역을 추가합니다.JCrop. 이제 내 질문에 올랐습니다. 투명 사각형의 특정 영역 내에서 객체 배치를 제한하고 싶습니다. 제한된 영역에 있어야하는 텍스트/이미지/모양을 추가하고 싶습니다. 배경 이미지, 투명 사각형의 위치 및 심지어 원 모양 개체를 구현할 수 있지만 투명 사각형 안에 개체를 배치하는 세부 정보를 찾을 수 없습니다 그리고 그 지역에서만.

여기 내 코드와 작업이 있습니다.깡깡이, 이미지를 자르면 자르기 부분을 선택해야하는 이미지와 해당 캔버스 배경 아래에 자르기 선택과 같은 투명한 사각형이있는 투명한 사각형이 표시됩니다. 이제 투명 사각형에 객체 배치를 제한하고 싶습니다. 지금 캔버스의 어느 곳에 나 객체를 배치 할 수 있습니다.

HTML

  <img src="https://images.unsplash.com/photo-1595438337199-d50ba5072c7e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=330&q=80" id="target">
   <div class="canvas-container" style="position: relative; user-select: none;">
     <canvas id="c1" width="600" height="600" style="border:1px solid #ccc; position: absolute;  left: 0px; top: 0px; touch-action: none; user-select: none;"></canvas>
   </div>

JS

function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
  var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
  return {
    width: srcWidth * ratio,
    height: srcHeight * ratio,
    aspectratio: ratio
  };
}
jQuery(function($) {
    //alert("Testing");
  var img = new Image();
  img.onload = function() {
    var data = calculateAspectRatioFit(this.width, this.height, '400', '600');
    console.log(data);
    jQuery('#target').attr('width', data.width);
    jQuery('#target').attr('height', data.height);
    jQuery('#pdr-drawing-area').html("Aspect Ratio: " + data.aspectratio);
    const stage = Jcrop.attach('target');
    stage.listen('crop.change', function(widget, e) {
      const pos = widget.pos;
      console.log(pos.x, pos.y, pos.w, pos.h);
      //fabric js
      var canvas = new fabric.Canvas('c1');
      var center = canvas.getCenter();
      var img = 'https://images.unsplash.com/photo-1595438337199-d50ba5072c7e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=330&q=80';
      canvas.setBackgroundImage(img, function() {
        canvas.backgroundImage && canvas.backgroundImage.scaleToWidth(data.width);
        canvas.backgroundImage && canvas.backgroundImage.scaleToHeight(data.height);
        //canvas.sendToBack(img);
        canvas.renderAll();
      });
      console.log(pos.x * data.aspectratio);
      var rect = new fabric.Rect({
        left: pos.x,
        top: pos.y,
        fill: 'transparent',
        width: (pos.w),
        height: (pos.h),
        strokeDashArray: [5, 5],
        stroke: "black",
        selectable: false,
        evented: false,
        //visible: false
      });
      canvas.add(new fabric.Circle({
        radius: 30,
        fill: '#f55',
        top: pos.y + 2,
        left: pos.x + 2
      }));
      canvas.add(rect);
      canvas.setHeight(data.height);
      canvas.setWidth(data.width);
      canvas.renderAll();
    });
  },
   img.src = 'https://images.unsplash.com/photo-1595438337199-d50ba5072c7e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=330&q=80';
});


  • 답변 # 1

    FabricJS에서 움직임을 제한하는 방법의 예는 다음과 같습니다.
    캔버스의 stateful 속성을 사용하고 있습니다. function objectMoving 이하.

    var canvas = new fabric.Canvas("canvas");
    canvas.stateful = true;
    function inside(p, vs) {
        var inside = false;
        for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
            var xi = vs[i].x, yi = vs[i].y;
            var xj = vs[j].x, yj = vs[j].y;
            var intersect = yi > p.y !== yj > p.y && p.x < ((xj - xi) * (p.y - yi)) / (yj - yi) + xi;
            if (intersect) inside = !inside;
        }
        return inside;
    }
    function getCoords(rect) {
        var coords = []
        coords.push(rect.aCoords.tl);
        coords.push(rect.aCoords.tr);
        coords.push(rect.aCoords.br);
        coords.push(rect.aCoords.bl);
        coords.push(rect.aCoords.tl);
        return coords;
    }
    function objectMoving(e) {
        var cCoords = getCoords(parent);
        var inBounds = inside({ x: e.target.left + 30, y: e.target.top + 30 }, cCoords);
        if (inBounds) {
            e.target.setCoords();
            e.target.saveState();
        } else {
            e.target.left = e.target._stateProperties.left;
            e.target.top = e.target._stateProperties.top;
        }
    }
    var boundary = new fabric.Rect({
        width: 310, height: 170,
        left: 5, top: 5,
        selectable: false,
        strokeDashArray: [5, 2],
        stroke: "blue",
        fill: "transparent"
    });
    var parent = new fabric.Rect({
        width: 250, height: 110,
        left: 35, top: 35,
        selectable: false,
        strokeDashArray: [2, 5],
        stroke: "black",
        fill: "transparent"
    });
    var child = new fabric.Circle({
        radius: 30,
        fill: "rgba(255,0,0,0.8)",
        top: 50, left: 50,
        hasControls: false,
    });
    canvas.add(boundary);
    canvas.add(parent);
    canvas.add(child);
    canvas.on("object:moving", objectMoving);
    
    
    <canvas id="canvas" width="400" height="180"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.min.js"></script>
    
    

    에서 function inside 레이 캐스팅 알고리즘을 사용하고 있습니다. 자세한 내용은 여기를 참조하십시오. https://github.com/substack/point-in-polygon/blob/master/index.js
    이 알고리즘은 나중에 부모 경계로보다 복잡한 모양을 허용하기 위해 문을 열어 모든 모양의 다각형으로 작동 할 수 있기 때문에 선호합니다.

    해당 코드에 대한 설명이 필요하면 알려주십시오.

    <시간 />

    이제 "JCrop"선택에서 사용자에서 변경 될 때 부모 경계를 동적으로 변경해야합니다.

관련 자료

  • 이전 Flutter Flexible Text가 열에 넘칩니다
  • 다음 javascript - lodash를 사용하여 내부 객체 반복