Uploading images with element addition in the image

0

Hello, I need to upload where, in the image, the client can add a visual element to mark something. I'll need something via javascript to do the visual interaction before the upload (simpler part).

Does anyone know how to do this?

For example, in the image below I took the photo of any room and added an arrow pointing to an element of the room. This is what I need to do, can anyone help me?

[Update]

Basedonthesolutionprovidedbysomepeople,includingValdirPsrthatsentagreatsolution,searchingalittlemoreIfoundalibcalledFabric.jsandmanagedtomakeanimplementationthatIconsideredsimpler.

[Solution]

Forthoseinterested,followtheexampleprojectIcreatedingithub: link

    
asked by anonymous 10.02.2018 / 03:01

1 answer

1

One way to do this is by using canvas and the events of Drag And Drop , native, HTML5 .

Demo
Project Download

Dragging and dropping an object on the screen

To use the draggable option is quite simple. Just set the draggable="true" attribute on the element to be dragged. In case the arrow.

<div id="img">
    <img id="main" src="http://via.placeholder.com/350x350?text=Clique+para+carregar+uma+imagem"/><imgid="arrow" draggable="true" src="arrow.png" />
    <canvas style="display:none"></canvas>
</div>

Now we just need to capture the position value relative to the element.

In the ondragstart function, we capture where the element "left".

imgArrow.addEventListener("dragstart", (ev) => {
    /* Capturamos o valor da propriedade 'left' e 'top' do CSS */
    let left = ev.target.style.getPropertyValue("left") || 0;
    let top = ev.target.style.getPropertyValue("top") || 0;

    /* Subtraímos a posição do elemento em relação a posição dele na tela e salvamos para consultar posteriormente. */
    ev.dataTransfer.setData("left", parseInt(left) - ev.clientX);
    ev.dataTransfer.setData("top", parseInt(top) - ev.clientY);
});

In function ondragover , we validate the action drop .

imgArea.addEventListener("dragover", (ev) => {
    ev.preventDefault();
    return false;
});

In the ondrop function, we will capture the position x and y from where the object was dropped and we will capture the previously set values to calculate the new position of the object.

imgArea.addEventListener("drop", (ev) => {
    /* Capturamos os valores "x" e "y" setado anteriormente */
    let left = ev.dataTransfer.getData("left") || 0;
    let top = ev.dataTransfer.getData("top") || 0;

    /* Somamos o valor setado anteriormente com a nova posição do objeto em relação a tela */
    imgArrow.style.left = parseInt(left) + ev.clientX;
    imgArrow.style.top = parseInt(top) + ev.clientY;
});
Ready! We already have the effect of dragging and dropping the arrow.

Saving the new image.

Now let's work with canvas to manipulate our new image. For this we will use only the context and the drawImage method of the cited element.

/* Aqui setamos a largura e altura do canvas */
this.canvas.width = imgMain.width;
this.canvas.height = imgMain.height;

/* Capturamos o contexto */
let ctx = this.canvas.getContext("2d");

/*
 * Aqui nós desenhamos a imagem principal no canvas.
 * Adiciona a imagem na posição x=0 e y=0 juntamente 
 * com a largura e altura da imagem
 */
ctx.drawImage(imgMain, 0, 0, imgMain.width, imgMain.height)

/*
 * Aqui nós desenhamos a seta no canvas.
 * Adiciona a imagem na posição definidos no 'css' (left e top)
 * juntamente com a largura e altura da imagem
 */
ctx.drawImage(imgArrow, parseInt(imgArrow.style.left), parseInt(imgArrow.style.top), imgArrow.width, imgArrow.height);

Ready. Finished one more part.

Sending the image to the server.

In this last step there is also no headache. Just use the toBlob method to capture the file and XHR to send to the server.

canvas.toBlob(blob => {
    let form = new FormData();
    form.append("file", blob);

    let xhr = new XMLHttpRequest();
    xhr.onload = function(result) { alert( result.target.responseText ); }
    xhr.open("POST", "upload.php", true);
    xhr.send(form);
});

Making things easier

Well, I ended up doing a very simple class. Just download the download link and use it as follows:

const imgArea = document.querySelector("#img");
const imgMain = document.querySelector("#img #main");
const imgArrow = document.querySelector("#img #arrow");
const btnDownload = document.querySelector("#btnDownload");

new DragAndDrop(imgArea, imgMain, imgArrow, {
    arrowHeight: 100, //Altura da seta
    arrowWidth: 100,  //Largura da seta
    btnDownload: btnDownload,  //Botão de Download

    //Eventos
    dragStart: () => {
        console.log("Start");
    },
    dragOver: () => {
        console.log("Over");
    },
    dragDrop: () => {
        console.log("Drop")
    }
});

Demo
Project Download

    
10.02.2018 / 21:33