Resizing an image with six corners using the canvas technique

Currently, I am facing two issues:

  1. The topcenter, bottomcenter, left and right anchors are not clickable.
  2. I'm struggling with the logic to adjust the image size proportionally as described below:
    1. The corner anchors should resize both height and width simultaneously.
    2. The non-cornered anchors should resize accordingly as illustrated in the provided image.

This is how I envision the implementation:

I've set up a canvas where I draw an image and handle resizing. Here's my simple HTML structure:

<canvas width="700px" height="700px" id="canvas"></canvas>

And here's the accompanying script:

// The JavaScript code 
var canvas = document.getElementById("canvas");
// More script follows...

You can view the actual output here.

I would appreciate it if you could assist me in resolving the issue of the non-cornered anchors being unresponsive and guide me on correctly resizing the image based on the anchor positions as outlined above and demonstrated in the image. Your help would be greatly appreciated. :)

**Note: **I do not have access to jQuery for this task.

Answer №1

Check out my response over here: Changing the origin of a canvas drawn image

I'll also repeat the solution below just in case someone finds this page through Google instead.

An effective method for resizing as desired is to keep one or more sides fixed while allowing another side to be adjusted by dragging a side or corner.

An added advantage of this approach is that you don't necessarily need visible anchors to resize!

This mirrors how operating system windows function.

When you resize windows on your desktop, you typically drag from the side or corner without any visible anchor points to guide you.

Here's a demonstration: http://jsfiddle.net/m1erickson/keZ82/

  • Left: original image,
  • Middle: resized from bottom-left corner with aspect ratio maintained (top-right corner remains unchanged)
  • Right: resized from bottom only, causing vertical scaling exclusively (top edge of image remains stationary)

Please note that although this demo and example show anchors, they are purely cosmetic. You can disable the anchor display and still resize the image by dragging the sides or corners.

Sample code:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var isDown=false;

    var iW;
    var iH;
    var iLeft=50;
    var iTop=50;
    var iRight,iBottom,iOrientation;

    var img=new Image();
    img.onload=function(){
        iW=img.width;
        iH=img.height;
        iRight=iLeft+iW;
        iBottom=iTop+iH;
        iOrientation=(iW>=iH)?"Wide":"Tall";
        draw(true);
    }
    img.src="facesSmall.png";

    var border=10;
    var isLeft=false;
    var isRight=false;
    var isTop=false;
    var isBottom=false;
    var iAnchor;

    canvas.onmousedown=handleMousedown;
    canvas.onmousemove=handleMousemove;
    canvas.onmouseup=handleMouseup;
    canvas.onmouseout=handleMouseup;


    function hitResizeAnchor(x,y){

        // determine which borders are under the mouse
        isLeft=(x>iLeft && x<iLeft+border);
        isRight=(x<iRight && x>iRight-border);
        isTop=(y>iTop && y<iTop+border);
        isBottom=(y<iBottom && y>iBottom-border);

        // return the appropriate anchor based on position
        if(isTop && isLeft){ return(iOrientation+"TL"); }
        if(isTop && isRight){ return(iOrientation+"TR"); }
        if(isBottom && isLeft){ return(iOrientation+"BL"); }
        if(isBottom && isRight){ return(iOrientation+"BR"); }
        if(isTop){ return("T"); }
        if(isRight){ return("R"); }
        if(isBottom){ return("B"); }
        if(isLeft){ return("L"); }
        return(null);
    }

    var resizeFunctions={

        T: function(x,y){ iTop=y; },
        R: function(x,y){ iRight=x; },
        B: function(x,y){ iBottom=y; },
        L: function(x,y){ iLeft=x; },

        WideTR: function(x,y){
            iRight=x;
            iTop=iBottom-(iH*(iRight-iLeft)/iW);
        },
        TallTR: function(x,y){
            iTop=y;
            iRight=iLeft+(iW*(iBottom-iTop)/iH);
        },

        WideBR: function(x,y){
            iRight=x;
            iBottom=iTop+(iH*(iRight-iLeft)/iW);
        },
        TallBR: function(x,y){
            iBottom=y;
            iRight=iLeft+(iW*(iBottom-iTop)/iH);
        },

        WideBL: function(x,y){
            iLeft=x;
            iBottom=iTop+(iH*(iRight-iLeft)/iW);
        },
        TallBL: function(x,y){
            iBottom=y;
            iLeft=iRight-(iW*(iBottom-iTop)/iH);
        },

        WideTL: function(x,y){
            iLeft=x;
            iTop=iBottom-(iH*(iRight-iLeft)/iW);
        },
        TallTL: function(x,y){
            iBottom=y;
            iLeft=iRight-(iW*(iBottom-iTop)/iH);
        }
    };

    function handleMousedown(e){
         // indicate that we will handle this mousedown event
         e.preventDefault();
         e.stopPropagation();
         var mouseX=e.clientX-offsetX;
         var mouseY=e.clientY-offsetY;
         iAnchor=hitResizeAnchor(mouseX,mouseY);
         isDown=(iAnchor);
    }

    function handleMouseup(e){
         // indicate that we will handle this mouseup event
         e.preventDefault();
         e.stopPropagation();
         isDown=false;
         draw(true);
    }

    function handleMousemove(e){
         // indicate that we will handle this mousemove event
         e.preventDefault();
         e.stopPropagation();
         // exit if not currently dragging
         if(!isDown){return;}
         // obtain current MouseX/Y coordinates
         var mouseX=e.clientX-offsetX;
         var mouseY=e.clientY-offsetY;

         // update iLeft, iRight, iTop, iBottom based on drag operation
         resizeFunctions[iAnchor](mouseX,mouseY);

         // redraw the resized image
         draw(false);
    }


    function draw(withAnchors){
        var cx=iLeft+(iRight-iLeft)/2;
        var cy=iTop+(iBottom-iTop)/2;
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.drawImage(img,iLeft,iTop,iRight-iLeft,iBottom-iTop);   
        if(withAnchors){
            ctx.fillRect(iLeft,iTop,border,border);
            ctx.fillRect(iRight-border,iTop,border,border);
            ctx.fillRect(iRight-border,iBottom-border,border,border);
            ctx.fillRect(iLeft,iBottom-border,border,border);
            ctx.fillRect(cx,iTop,border,border);
            ctx.fillRect(cx,iBottom-border,border,border);
            ctx.fillRect(iLeft,cy,border,border);
            ctx.fillRect(iRight-border,cy,border,border);
        }
    }

}); // end $(function(){});
</script>
</head>
<body>
    <h4>Adjusting image dimensions</h4>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

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

What is the best way to retrieve ember model relation properties within routes and controllers?

Currently using ember 2.7.0, I am facing an issue while setting up my ember app with a currentUser.organization derived from the authenticated token. Although I can successfully resolve the currentUser, I am encountering difficulties in resolving the prope ...

What is the best way to reference an i18n entry within .json files?

I am in the process of creating a user interface using SAP UI5 and my goal is to make all text elements internationalized. Below is a snippet of my view in .xml format where I successfully retrieve text in different languages using placeholders enclosed i ...

What is the best way to halt a window.setInterval function in JavaScript?

I have a JavaScript function that runs every 2000ms. I need to find a way to pause this function so that the user can interact with other elements on the page without interruptions. Is there a way to achieve this? Below is the code for the function: win ...

Organizing content into individual Div containers with the help of AngularJS

As someone who is new to the world of AngularJS, I am currently in the process of learning the basics. My goal is to organize a JSON file into 4 or 5 separate parent divs based on a value within the JSON data, and then populate these divs with the correspo ...

When the onClick event is triggered, my intention is to dynamically insert a new

I'm having trouble adding a new row on each click, as my code keeps replacing the existing row. I attempted moving the if statement outside the addTable function, but it didn't work as expected. I've tried multiple solutions without succes ...

Align the tops of the tables

I currently have three tables in my HTML code. When all three tables are filled with data (10 rows each), they appear correctly aligned as shown in the first picture. However, if any of the tables do not have the maximum capacity of 10 rows reached, they ...

I am not getting any reply in Postman - I have sent a patch request but there is no response showing up in the Postman console

const updateProductInfo = async (req, res) => { const productId = req.params.productId; try { const updatedProduct = await Product.findOneAndUpdate({ _id: productId }, { $set: req.body }); console.log("Product updat ...

``Using backticks to denote HTML syntax - Leveraging Google Charts to create

Has anyone found a way to incorporate HTML in ticks within a Google chart? I am attempting to insert a weather icon from This is my current attempt: const dailyData = new google.visualization.DataTable(); dailyData.addColumn('timeofday' ...

Sliding in a strange way

Are you experiencing a strange behavior with the slider on your website? When you hover over the image, the caption at the bottom slides up and on mouseout it slides down again. It works perfectly on . However, when navigating to portfolio via the menu on ...

Header Overflow Error Encountered in Node.js GET Request

While attempting to programmatically submit a form through Google forms using a GET request, I encountered the error message Parse Error: Header overflow. The debug code output is as follows: REQUEST { uri: 'https://docs.google.com/forms/d/e/9dSLQ ...

Dynamically Remove One Form from a Django Formset

I have been using the following code to dynamically add a form to my formset: .html {{ form2.management_form }} <div id="form_set"> {% for form2 in form2.forms %} <table class="table table2" width=100%> ...

Tips for eliminating any default white space visible between tags:

What is the best way to eliminate white space gaps between div tags and adjust pixel differences between them in HTML code? My current alignment is off and there are noticeable white spaces between div tags. I have tried using a reset link but it didn&apo ...

Challenges with rendering text in Three.js

We are currently working on a project in three.js and facing difficulties when it comes to loading fonts onto our text elements. Our approach involves using the TextGeometry object for rendering fonts and the typeface js converter to incorporate new fonts ...

Configuring static files in Django for hosting a website in production mode

I have been attempting to serve my static files from the same production site in a different way. Here are the steps I took: First, I updated the settings.py file with the following: DEBUG = False ALLOWED_HOSTS = ['12.10.100.11', 'localhos ...

The jQuery datatable is functioning correctly, however the button is rendered but is not

Originally, I have a datatable which can be viewed at the following link: The functionality I am experiencing is related to a "DISABLE" button that toggles to "ENABLE" and vice versa upon clicking. However, if you click on the same button after it has alr ...

When using <body onload=foo()>, the function foo will not be executed

Having trouble with this code - it seems like initialize() is not being called. Check out the code here Any insight into why this might be happening? ...

What is the best way to incorporate and execute a separate JavaScript file in a Node application using Express JS?

I am attempting to configure a javascript file that is responsible for grabbing an RSS feed and storing the information in a database. Originally, I had this file called by the HTML page, but now I want it to continuously run in the back-end (constantly re ...

What is the best way to execute multiple controller functions for a single route?

I have a specific route set up for users to submit loan applications. What I want to achieve is to call different controller functions based on the amount of the loan that the user is applying for. app.use('/submitLoanRequest50kMore', mw1, mw2, ...

Using Firebase onDisconnect with React Native

I am currently working on a React Native app and I am facing an issue where I need to update the user status to 'offline' in Firebase when the user closes the app. Here is what I have tried: import React, { Component } from 'react' ...

What is the best way to convert my JSON data to HTML using JavaScript?

My dilemma seems to be rooted in the use of backticks. Strangely, an error keeps popping up whenever I try to employ them in my IDE (Brackets). I attempted solutions by testing directly in my Browser and through NotePad++, but unfortunately, nothing seeme ...