TypeScript

by iammapping

HTML

<script src="https://fabricjs.com/lib/fabric.js"></script>
<canvas id="c" width="500" height="500"></canvas>

CSS

.canvas-container {
  border: 2px solid #DDD;
}

TypeScript

var canvas = new fabric.Canvas('c');
canvas.selection = false;
canvas.clipPath = new fabric.Rect({width: 300, height: 500, top: (canvas.height - 500) / 2, left: (canvas.width - 300) / 2});
var clipPath = new fabric.Rect({ width: 250, height:150, top: 125, left: 125, absolutePositioned: true, strokeWidth: 0 });
fabric.Image.fromURL('http://fabricjs.com/lib/pug.jpg', function(img) {
  img.hasRotatingPoint = false;
  img.clipPath = clipPath;
  //img.centeredScaling = true;
  var lowScale = Math.max(clipPath.width / img.width, clipPath.height / img.height);
  img.scaleToWidth(img.width * lowScale);
  makeTargetOutClip(img);
  canvas.add(img);
});
var dummy, target;
canvas.on('selection:created', function(options) {
	target = options.target;
  target.clone(function(obj) {
  	dummy = obj;
    delete dummy.clipPath;
    dummy.selectable = false;
    dummy.opacity = 0.5;
    canvas.add(dummy);
  });
}).on('object:moving', function(options) {
	if (options.target !== target || !dummy) return;
    fellowWithTarget(dummy, target);
}).on('object:scaling', function(options) {
	if (options.target !== target || !dummy) return;
  fellowWithTarget(dummy, target);
}).on('object:moved', function(options) {
	if (options.target !== target || !dummy) return;
  fellowWithTarget(dummy, target);
}).on('selection:cleared', function(options) {
	if (!dummy) return;
	canvas.remove(dummy)
});

function fellowWithTarget(dummy, target) {
	makeTargetOutClip(target);
	dummy.set({
  	left:target.left,
    top: target.top,
  	scaleX: target.scaleX,
    scaleY: target.scaleY
  })
}

var lastScale;
function makeTargetOutClip(target) {
	if (!target.clipPath) return;
  var lowScale = Math.max(target.clipPath.width / target.width, target.clipPath.height / target.height);
  var scale = Math.max(lowScale, target.scaleX != lastScale ? target.scaleX : target.scaleY);
  
  target.set({
  	left: target.left > target.clipPath.left ? target.clipPath.left : Math.max(target.left, target.clipPath.left -...