In Javascript, swap out a particular colored region in an image with a different image

I've been scouring the internet in search of a solution to my problem, but it seems like I might not be looking in the right places.

Imagine this image below, how can I replace the blue area with an image uploaded by the user? I'm struggling to figure out how to achieve this.

I stumbled upon this which talks about drawing a red rectangle based on specific coordinates, but what I need (I believe) is to identify those coordinates and swap them out with an image. Has anyone encountered this before? Any guidance would be greatly appreciated as I'm stuck here!

https://i.sstatic.net/rrGp5.jpg

Please note that the image used here is just for illustrative purposes and does not belong to me. Thank you for your help.

EDIT:

I realize I should have included the code initially, apologies for that oversight. This project is built using phonegap and jquery mobile, with a navbar at the bottom. One of the pages, named "preview," requires the functionality to change images, but I seem to be missing something due to lack of knowledge:

My index.html:

 <div data-role="page" data-url="preview" id="preview">
      <div data-role="header" style="background-color: rgb(182, 202, 51)" data-position="fixed">
        <h1 id="titlePreview">PREVIEW</h1>
        <a href="#language" id="langBtn" style="width: 20px;height: 20px; background:none;  " href="#" data-icon="comment" data-iconpos="notext" class="ui-btn-left"></a>
      </div>
        <div id="previewSaco" class="containerPreviewSaco">//if i remove this div, the navbar on the bottom disapears. 
          <canvas id="myCanvas" width="200" height="200">//i´m testing with this size, but yes the image is supose to have a 100% with, in fact the image as 1940x2372. 
       </div>
      <div data-role="footer" data-position="fixed">
        <div data-role="navbar" class="ui-bar">
          <ul>
            //in here i have my several "li" for navegation and i think it´s irrelevant for my question.
          </ul>
        </div>
      </div>
    </div>

My .js file:

$(document).on("click", "#btnPreview", function (event) {

    var ctx = document.getElementById('myCanvas').getContext('2d');

    var img = new Image;
    img.onload = function(){
      ctx.drawImage(img,0,0);
      img2.src = 'img/capa.png'; 
    };

    var img2 = new Image;
    img2.onload = function(){
        ctx.globalCompositeOperation = 'destination-over';

      //ctx.scale(x, y);
      //ctx.rotate(angle);
      //ctx.translate(x, y);

      //or

      //ctx.transform(a, b, c, d, e, f);

      ctx.drawImage(img2,0,0);
    };

    var uri1 = 'img/previewSaco1.png'; //the main image supposed to load on page click "preview", **but it's not happening** also featuring a transparent area for user-uploaded images.

    var uri2 = 'img/capa.png';//a dummy logo image for larger image testing
    img.src = uri1;
});

Note: when running the app, the phonegap desktop constantly displays: undefined Content Security Policy has been modified to be: https://ssl.gstatic.com;style-src 'self' 'unsafe-inline' data: blob:;media-src *;img-src * 'self' data: content:;script-src * 'unsafe-inline' 'unsafe-eval' data: blob:;">

Answer №1

Alright, let's dive in:

Utilize the following HTML structure:

<div id="imageContainer" class="center">
<h2>Let's explore and see where it leads</h2>
<img class="pic" src="https://moltopiccolo.files.wordpress.com/2012/01/cool-drinks.jpg"> 
</div>

You have the flexibility to set any background image on the container div without affecting the layout.

The image employs CSS clip path which requires multiple prefixes for compatibility, but the visual results are stunning. You can shape your image using clip path generators available online and even animate it.

Here is an example of mine:

#imageContainer img {
-webkit-clip-path: polygon(1% 3%, 3% 9%, 18% 21%, 54% 20%, 83% 63%, 66% 76%, 
15% 83%, 25% 45%);
clip-path: polygon(17% 13%, 33% 9%, 58% 21%, 84% 20%, 83% 63%, 66% 76%, 15% 
83%, 25% 45%);
-webkit-transition: -webkit-clip-path .6s ease-out;
transition: -webkit-clip-path .6s ease-out;
position:absolute;
border-radius: 5px;
width: 100%;
height:270px;

}

I've also added an input button for file upload, along with the following JavaScript function:

var getval = document.querySelector("#getval");

getval.addEventListener("change", previewFile);

function previewFile() {
var reader = new FileReader();
var bgImage = document.querySelector(".pic");
var file = document.querySelector("input[type=file]").files[0];
reader.onloadend = function() {
bgImage.src = reader.result;
};

if (file) {
reader.readAsDataURL(file); //reads the data as a URL
 } else {
file.src = "";
}
}

For a demonstration, visit this link:

https://codepen.io/damianocel/pen/KdobyK

Answer №2

To achieve a layered effect in your canvas drawing, consider using the

Context2D.globalCompositeOperation = 'destination-over';
. For more detailed information, visit GlobalCompositeOperation documentation.

Start by editing your image in an editor and removing the section you wish to replace by making those pixels transparent. Then, load this modified image onto the canvas.

Next, load the new image you want to insert. Use

ctx.globalCompositeOperation = 'destination-over';
to superimpose this image on top of the existing one in the canvas.

If needed, apply a transformation to the canvas before adding the second image for better alignment.

Refer to this example on jsfiddle: jsfiddle.net

Edit 1: Instead of manually setting transparency, consider adjusting it based on color after loading the initial image. This answer on stackoverflow might help: this answer.

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

Comparing document.getElementById and the jQuery $() function

Is this: var contents = document.getElementById('contents'); The equivalent to this: var contents = $('#contents'); Considering that jQuery is present? ...

Guide for integrating images in React Native

I am struggling to display images in a carousel properly. I attempted to require them using JSON like this {"Image": require("$PATH")} or in a js file within the ParallaxImage tag, but nothing seems to work... Item Creator _renderItem ...

Is there a way to remove background-color for a:focus?

When working with Twitter Bootstrap, I encountered a challenge. The background-color properties set for navigation items on the :focus state were causing an issue for a specific navigation element that needed have its own styling. Imagine a scenario where ...

Iterate over the key-value pairs in a loop

How can I iterate through a key-value pair array? This is how I declare mine: products!: {[key: string] : ProductDTO}[]; Here's my loop: for (let product of this.products) { category.products.push((product as ProductDTO).serialize()); } However, ...

Discovering the method to retrieve the values from 2 dropdown lists that are populated by a JavaScript function

I have a pair of dropdown lists in a JSP file labeled 'speciality' and 'super_speciality'. Clicking on an option in the 'speciality' dropdown list dynamically populates options in the 'super_speciality' dropdown list ...

What are effective strategies to stop the generic * { … } style from overriding its parent tag?

How can I prevent my general * { ... } style from overriding the parent tag? In the given scenario, I want the text "sssssssss" to have the style text-huge. .text-huge { font-size: 28px !important; color: green !important; } * { font-size: 12px; ...

Include a character in a tube using Angular

Hey everyone, I have a pipe that currently returns each word with the first letter uppercase and the rest lowercase. It also removes any non-English characters from the value. I'm trying to figure out how to add the ':' character so it will ...

unable to properly display application.html.erb

I am encountering difficulties in rendering my application.html.erb template as I am receiving the following error message: ActionView::SyntaxErrorInTemplate within ApplicationController#home app/views/layouts/application.HTML.erb:10: syntax error, unexpec ...

Modifying Checkbox BorderWidth in Material UI v5

Seeking assistance with adjusting the checkbox border width in Material UI v5. I currently have a custom checkbox and would like to remove the border width. Despite trying numerous solutions, I have been unsuccessful so far. checkbox <Checkbox de ...

Clone the children of an li element using jQuery, modify the text within a child tag, and then add it to

I have some awesome CSS that I want to recycle within a <ul>. My plan is to duplicate an existing <li> (to leverage the CSS), modify a <p> element, and then add it at the end of the <ul>. I believe I can achieve this by locating... ...

Having trouble retrieving values from multiple checkboxes in HTML

I have a HTML table displaying all the items from my SQL database. Each item has a checkbox that is supposed to pass the value of the item name to the calculation route when the submit button is pressed. However, the issue is that the submit button only ...

Steps for updating the nested array object using the unique identifier: "id"

Having trouble updating the nested state array in my module where users scan QR codes to update tracking numbers. Currently, I am using react js for frontend and Laravel for backend. Issue: When scanning the QR code, the tracking number is not being set t ...

Enhanced browsing experience with personalized search suggestions

As a developer, I am aware that you have the ability to customize the browser's suggestions for various fields. For example, specifying that a field is for email and only suggesting values for email fields in the future. Is this functionality really ...

The edit functionality in jqGrid does not function properly if custom search parameters are designated

Using the Guriddo jqGrid JS version 5.2.0 implemented here: @license Guriddo jqGrid JS - v5.2.0 - 2016-11-27 Copyright(c) 2008, Tony Tomov, [email protected] The code block below showcases an entire self-contained implementation of jqGrid. It inclu ...

Enhance your user interface with an interactive Bootstrap dropdown using Angular

I have a program where users can choose from 3 options such as: Hi, Hello and Hey. Currently, when a user selects one of the values, they receive a message saying that they need to "select a value." I am struggling to figure out how to update the ng-model ...

CSS - setting all child elements to the height of the tallest child element

Is there a way to ensure that both fieldsets have the same height as the tallest one? See the code snippet below or visit this link for reference: http://jsfiddle.net/zpcXQ/2/ <div id="parent"> <form> <fieldset id="left"> ...

Left-aligned and centered - Bootstrap

I need help figuring out how to center a list of items on the page, but have them aligned left. I am using bootstrap. I want the text to be in the center of the page but aligned left. <ul class='text-center'> <li class=& ...

Accessing a JSON file over a network using JavaScript

Struggling to access a basic data file using JavaScript, and it's proving to be quite challenging. The file will be hosted on a remote server and ideally accessed via HTTP. While I'm new to JavaScript, I've come across JSONP as a potential s ...

Tips for creating a functional null option using the select ng-options feature

While there are a few questions and answers on this topic, I have yet to find a solution that works for my specific case. Imagine having an object like this: $scope.person = {name: 'Peter', category1: null, category2: null}; Another variable r ...

The optimal method for storing tokens in Vue when using Laravel Sanctum

I am currently working on an application built with Laravel and Vue.js. My current focus is implementing the login/logout functionality using Laravel Sanctum. Here is my scenario: I already have the backend methods for login/logout/register set up, but I ...