Create an Oval-Shaped Image Cutout

Currently, I have a fabric.JS canvas where objects can be added. However, I am interested in clipping these objects into an oval shape, similar to the clip demos on fabricjs.com.

In my current project (JSFiddle), I have been able to crop the object into a circle shape.

var canvas = new fabric.Canvas("c");
canvas.isDrawingMode = false;

// create a rectangle object
var rect = new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'red',
  width: 200,
  height: 200
});

$("#clipCircle").click(function() {
  var obj = canvas.getActiveObject();
  if (!obj) return;

  if (obj.clipTo) {
    obj.clipTo = null;
  } else {
    var radius = obj.width < obj.height ? (obj.width / 2) : (obj.height / 2);
    obj.clipTo = function(ctx) {
      ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
    };
  }
  canvas.renderAll();
});

// "add" rectangle onto canvas
canvas.add(rect);

// select, draw
$("#select").click(function() {
  canvas.isDrawingMode = false;
});
$("#draw").click(function() {
  canvas.isDrawingMode = true;
});
var activeObject = null;
canvas.on('selection:created', function(options) {
  activeObject = options.target;
  $("#alpha").slider("option", "value", activeObject.opacity);
});
canvas.on('selection:updated', function(options) {
  activeObject = options.target;
  $("#alpha").slider("option", "value", activeObject.opacity);
});
canvas.on('selection:cleared', function(options) {
  activeObject = null;
});
$("#alpha").slider({
  max: 1,
  min: 0,
  step: 0.1,
  value: 1,
  slide: function(event, ui) {
    activeObject && (activeObject.opacity = ui.value)
    canvas.requestRenderAll();
  },
  stop: function(event, ui) {
    canvas.requestRenderAll();
  }
});
canvas {
  border: solid 1px #000;
}

fieldset {
  max-width: 350px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<br>
<button id="draw">Draw</button>
<button id="select">Select</button>
<button id="clipCircle">Crop to Circle</button>
<button id="clipOval">Crop to Oval</button>
<br>
<br>
<fieldset>
  <legend>Controls</legend>
  <label for="alpha">Opactity</label>
  <div id="alpha" name="alpha"></div>
</fieldset>

I would appreciate any guidance on how to achieve this oval cropping effect. Thank you!

Answer №1

My solution involves scaling the ctx to 0.5 on one axis, allowing you to create an oval shape from a normal sphere and then restoring the ctx.

const radius = obj.width < obj.height ? (obj.width / 2) : (obj.height / 2);
obj.clipTo = function(ctx) {
    ctx.scale(0.5, 1);
    ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
    ctx.restore();
};

Screenshot:

When applying this clipping method to your red cube object, it produces the following red shape:

https://i.sstatic.net/2Sltd.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Has Angular been assimilated into the window object by webpack?

I'm encountering a puzzling issue with webpack that I can't seem to resolve. Here is the link to my webpack.config file: https://github.com/saike/maluvich-browser/blob/master/webpack.config.babel.js In my project, I import angular using ES6 mo ...

Is it possible to have more than one button for each item on my Shopping List App?

I am developing a shopping list app that allows users to add items to a list. Each item added triggers the display of a button next to it, enabling users to remove the item from the list when needed. However, a problem arises as more items are added – i ...

Is there a proper method in AngularJS for factories to return objects?

I am facing an issue in retrieving POST data in an Angular.js project. This is the factory I am using: angular.module('mtApp').factory('getKey', function($http) { return { getData: function(data) { var key=&apos ...

Command to conceal components for users visiting as guests

I'm looking to develop a directive that hides specific elements for guest users. Here is the current code I have: angular.module('someMod') .directive('premiumUser', premiumUser) .controller('PremiumUserCtrl', Pr ...

Remove the background color from a semi-transparent circular CSS div when it is being dragged

My circular div is being dragged for a drag and drop operation, but there's always a translucent square around it. How can I remove this unwanted effect? body{ background : #BBD1DF; } .dragdemo { width: 170px; height: 170px; line-hei ...

Error: Failed to find the location because geolocate has not been defined

I searched extensively online for a solution to my problem without success, so I am reaching out to seek your assistance. I am attempting to utilize the Google Address auto-complete API within an asp.net core framework. In my razor file, I have included: ...

I rely on the handleChange function to update the state value, but unfortunately, it remains unchanged

In my project, I am working on creating multiple responsive forms (form1, form2, and form3) within the same page using framer motion. However, I am facing an issue where the state value is not updating correctly when users fill out the form. Specifically, ...

Adjust the height of the Accordion component in Material UI

I am currently in the process of migrating a JavaFx HMI to a web application that utilizes React.js. To display graphical widgets, I am also working with Material.ui. In order to maintain consistency with the original HMI layout, I need to adjust the layo ...

A step-by-step guide to implementing the PUT function in AngularJS using Mongoose

My attempt to send a GET request to the Mongo works fine, but I'm having trouble getting the PUT request to work. My suspicion is that there might be an issue with the path from the controller to the router. I've already tried using both update() ...

Discover the syntax for reading route parameters in Angular

Currently, I am integrating the Paypal API into my project. After confirming a purchase, Paypal redirects to a specified URL. I set the desired URL as "localhost:4200/shop/order". However, when Paypal returns the URL, it appends the token and payerid at th ...

Store the JSON reply as a fixed variable

Recently, I have been delving into ReactJS and I've encountered a challenge of saving a JSON array as a 'const'. I have attempted the following approach: fetch(url) .then(response => response.json()) .then(json => { this.setSt ...

Troubleshooting Cross-Origin Read Blocking with the Google Maps Elevation API using Axios in a Vue.js Application

I'm currently working on integrating the Google Maps API into a Vue.js project. I've encountered an issue with two Google Maps services: - The Time Zone API is functioning properly. - However, the Elevation API is giving me a Cross-Origin Read Bl ...

Using blending modes with gradient colors in an SVG design

I'm struggling to get my logo to change colors upon scrolling into a button with similar gradient colors, but I just can't seem to make it work. Can anyone lend me a hand? Thank you! Take a look at my Logo. I've attempted to add some styles ...

I am looking to modify the highlighted table cell whenever the value within it changes

I am currently working on a small project related to the Stock Market. In this project, I need to dynamically change the style of the td element based on data fluctuations - green highlight for an increase and red highlight for a decrease. In the provid ...

Encountered an error while attempting to access the 'type' property of undefined within the Redux store for an action defined in an external package

In my quest to expand my knowledge of React (coming from an ASP.NET background), I encountered a challenge. I have multiple React applications where I intend to utilize common UI components, so I decided to extract these into a separate npm package. This a ...

Sending Data via Ajax

I am currently working on implementing an ajax invitation script that allows users to invite their friends to an event. The javascript code I have used in other parts of the website works perfectly, but for some reason, it is not functioning correctly in t ...

An Error with jQuery Autocomplete: "Callback is not Defined"

I am currently working on a jQuery script that involves autocomplete and selecting the correct value on the client side. Here is my functional code without the selected value (it displays all username available in my JSON): $(function() { $( "#us ...

I am consistently running into an Uncaught Syntax error within my Express server.js while using Angular 1.5.6

I've been struggling for hours to integrate Angular with routes that I've created. Eventually, I decided to give Express a try and set up a basic server.js file to run as a standalone server. However, nothing seems to be working and I keep encou ...

Having trouble retrieving data from the json file

Using Ajax to obtain a JSON update: $(document).ready(function(){ $('form').submit(function(event){ event.preventDefault(); var form = JSON.stringify($('form').serializeArray()); $.ajax ({ u ...

Creating dynamic height based on width using JavaScript

I'm trying to make a rectangle responsive based on the width of the window. This is my current logic: aspectRatio = 16 / 9 win = { width: window.innerWidth, height: window.innerHeight, } get browser() { const width = this.win.width - 250 ...