PK creative Spring Festival, I am participating in the “Spring Festival creative submission contest”, please see: Spring Festival creative submission Contest

In this article

By default, fabric.js does not provide right mouse button events, only mouse button click, mouse button lift, and mouse movement events. However, it is possible to use “right click” events at work, such as “right click menu”. Hence this article. This article focuses on the main apis of fabric.js:

  • fireRightClick: Allows right clicking
  • stopContextMenu: Disables the default right-click menu
  • mouse:down: Mouse click event



For those of you who don’t know fabric.js, see Fabric.js from Getting Started to ___.


This case is developed in the native way, not based on Vue, React and other frameworks, so there is no need to worry about the running environment and other problems.


The case code is at the end of the article





Environment and Version

Chrome version: 96.0.4664.45

Fabric.js version: 4.6.0




Train of thought

First, demand:

  • Right-click the element to pop up the menu;
  • The pop-up menu can be divided into four situations (the menu is on the right side of the mouse, the menu is on the left side of the mouse, the menu is above the mouse, and the menu is under the mouse).
  • Left-click elsewhere on the canvas to hide the menu;


Implementation idea:

  • Create canvas;
  • Create a DOM element for the menu.
  • Go to the official website to find “right-click related events”;
  • Right-click on the element and calculate the location of the menu to display according to the distance between the mouse and the edge of the canvas.
  • Left-click on the canvas to hide the menu;





implementation

Check the document

In the above idea, the only difficulty is “right-click related events”.

In object related documentation, mouse events don’t seem to have a right click, but a slightly closer mouse click (in this case I chose mousedown).


So I went to the document on the canvas and found these two properties:

  • fireRightClick :Whether a canvas can trigger a right-click event
  • stopContextMenu:Disable the default right-click menu

Hahaha, developed ~


The mouse: Down event has a button property:

  • left-click:buttonThe value of1
  • Right click:buttonThe value of3
  • In the key(Click on the wheel),buttonThe value of2Is requiredfireMiddleClick: true


Began to develop

layout

<style>
  /* Container, relative positioning */
  .box {
    position: relative;
  }

  /* Canvas, give a border */
  #canvas {
    border: 1px solid #ccc;
  }

  / * * / menu
  .menu-x {
    visibility: hidden; /* Hide menu */
    z-index: -100;
    position: absolute;
    top: 0;
    left: 0;
    box-sizing: border-box;
    border-radius: 4px;
    box-shadow: 0 0 4px rgba(0.0.0.0.3);
    background-color: #fff;
  }

  /* Menu for each option */
  .menu-li {
    box-sizing: border-box;
    padding: 4px 8px;
    border-bottom: 1px solid #ccc;
    cursor: pointer;
  }

  /* Mouse over option, change background color */
  .menu-li:hover {
    background-color: antiquewhite;
  }

  /* First option, the top two corners are rounded */
  .menu-li:first-child {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
  }

  /* Last option, the bottom two corners are rounded, the bottom does not need a border */
  .menu-li:last-child {
    border-bottom: none;
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
  }
</style>

<! -- Container (relative positioning) -->
<div class="box">
  <! - canvas - >
  <canvas id="canvas" width="600" height="600"></canvas>

  <! -- Right click menu (absolutely located and hidden by default) -->
  <div
    id="menu"
    class="menu-x"
  >
    <div class="menu-li">Do nothing</div>
    <div class="menu-li">Do nothing</div>
    <div class="menu-li">Do nothing</div>
    <div class="menu-li">Do nothing</div>
    <div class="menu-li" onclick="delEl()">delete</div>
  </div>
</div>
Copy the code

The effect is shown in the image above.


Initialize the canvas and generate the graphics

<script>
// Execute after the document is loaded
window.onload = function() {
  // Prints the current fabric version
  console.log(` Facrib. Js version:${fabric.version}`)

  // Initialize the canvas
  init()

  // Disable default right-click events on menus
  menu.oncontextmenu = function(e) {
    e.preventDefault()
  }
}

/ / initialization
function init() {
  canvas = new fabric.Canvas('canvas', {
    fireRightClick: true.// Enable the right button, button number is 3
    stopContextMenu: true.// Disable the default right-click menu
  })

  / / rectangle
  const rect1 = new fabric.Rect({
    left: 10.top: 510.fill: 'orange'.width: 40.height: 40
  })

  // Rounded rectangle
  const rect2 = new fabric.Rect({
    left: 510.top: 10.fill: 'pink'.width: 40.height: 40.rx: 10./ / the rounded x
    ry: 10./ / the rounded y
  })

  / / round
  const circle = new fabric.Circle({
    radius: 30./ / radius
    fill: 'green'.left: 20.top: 20,})/ / triangle
  let triangle = new fabric.Triangle({
    width: 80.// The bottom width
    height: 100.// The distance between the base and the fixed point
    fill: 'blue'.left: 500.top: 480
  })

  // Add the rectangle to the canvas
  canvas.add(rect1, rect2, circle, triangle)
}
</script>
Copy the code


Add click events (judge right click)

<script>
// omit some of the above code
function init() {
  // omit some code......
  // Add the rectangle to the canvas
  canvas.add(rect1, rect2, circle, triangle)

  // Press the mouse button
  canvas.on('mouse:down', canvasOnMouseDown)
}
    
// Mouse click events on the canvas
function canvasOnMouseDown(opt) {

  // Judge: right-click, and right-click on the element
  // opt. Button: 1- left button; 2 - the keys; 3 - right
  // On the canvas, click: opt.target is null
  if (opt.button === 3 && opt.target) {
    // Get the current element
    activeEl = opt.target

    menu.domReady = function() {
      console.log(123)}// Display menu, set right click menu location
    // Get the width and height of the menu component
    const menuWidth = menu.offsetWidth
    const menuHeight = menu.offsetHeight

    // The current mouse position
    let pointX = opt.pointer.x
    let pointY = opt.pointer.y

    // Calculate where the menu appears
    // If the mouse moves to the right of the canvas, the menu appears to the left of the mouse pointer
    if (canvas.width - pointX <= menuWidth) {
      pointX -= menuWidth
    }
    // If the mouse is near the bottom of the canvas, the menu appears above the mouse pointer
    if (canvas.height - pointY <= menuHeight) {
      pointY -= menuHeight
    }

    // Display the menu
    menu.style = `
      visibility: visible;
      left: ${pointX}px;
      top: ${pointY}px;
      z-index: 100;
    `
  } else {
    hiddenMenu()
  }
}

// Hide the menu
function hiddenMenu() {
  menu.style = ` visibility: hidden; left: 0; top: 0; z-index: -100; `
  activeEl = null
}

// Delete elements
function delEl() {
  canvas.remove(activeEl)
  hiddenMenu()
}
</script>
Copy the code


In the above code, the current clicked object is determined by whether opt.target is null.

Opt. target === null, which is clicked on the canvas (not on the graphic element).

If your project needs to right click on the canvas to also show different menus, you can modify the above code to judge.




Code warehouse

  • Native way to implement the Fabric right-click menu
  • Use Fabric to implement right-click menu functionality in Vue3




recommended

Fabric.js from Getting Started to Expanding


Fabric.js Gradients (including Radial gradients)





If this article is helpful to you, please give me a thumbs up