2016-01-02 3 views
0

J'ai créé une application de dessin HTML5 qui comporte des fonctions de base permettant à l'utilisateur de sélectionner une couleur à dessiner, de modifier la taille (rayon) de l'outil de dessin, d'annuler , refaire et effacer complètement la toile.Comment annuler l'action de gomme pour HTML5 Canvas Drawing App

J'ai récemment ajouté un outil Eraser utilisant globalCompositionProperty (desitnation-out) pour effacer les zones sélectionnées du canevas. Cette partie fonctionne bien, mais quand je vais annuler l'effacement, la toile entière est effacée et la fonction de rétablissement ne fonctionne pas. Lorsque je reprends le dessin avec l'outil de dessin standard (en utilisant la source), l'annulation/le rétablissement fonctionne. J'ai inclus le code pour quelques-unes des fonctions utilisées dans l'application. Je stocke un instantané de la toile chaque fois que l'outil de dessin est désengagé. Ceci est ajouté à un tableau qui est utilisé pour annuler et restaurer le canevas. Est-ce que quelqu'un peut expliquer ce que je pourrais faire mal ici? Je ne suis pas sûr de comprendre comment la propriété globalCompositeOperation affecte le canevas DataURI enregistré.

function storeSnapshot() { 
    cStep++; 
    if (cStep < cPushArray.length) { cPushArray.length = cStep; } 
    cPushArray.push(canvas.toDataURL()); 
} 

var putPoint = function(e){ 
    if(dragging){ 
    context.lineTo(e.clientX - 174, e.clientY - 50); 
    context.stroke(); 
    context.beginPath(); 
    if(eraser == true){ 
     context.globalCompositeOperation="destination-out"; 

    }else{ 
     context.globalCompositeOperation="source-over"; 
    } 
    context.arc(e.clientX - 174, e.clientY - 50 , radius, 0, 2 * Math.PI); 
    context.fill(); 
    context.beginPath(); 
    context.moveTo(e.clientX - 174, e.clientY - 50); 
    } 
} 

MISE À JOUR: Après avoir joué avec pendant un certain temps j'ai essayé quelque chose qui résout mon problème. Je ne suis pas vraiment sûr que ce soit la bonne façon de faire les choses, mais j'ai pensé que je te montrerais tout ce que j'ai fait.

J'ai une fonction de désengagement qui est déclenchée à la souris. Voici la fonction avant:

var disengage = function(){ 
dragging = false; 
context.beginPath(); 
storeSnapshot(); 
    } 

j'ai ajouté le morceau de code et cela permet à l'utilisateur d'utiliser l'outil Gomme et annuler/refaire l'action. Je ne sais pas exactement pourquoi cela fonctionne encore, donc si quelqu'un a un aperçu, je l'apprécierais grandement.

var disengage = function(){ 
dragging = false; 
context.beginPath(); 
if(eraser == true) 
{ 
    context.globalCompositeOperation="source-over"; 
} 
storeSnapshot(); 
    } 
+1

Lorsque vous enregistrez l'instantané, utilisez 'var data = ctx.getImageData (0,0, canvas.width, canvas.height)' ou, mieux encore, ne copiez que les parties du canevas que vous avez modifiées. Restaurer le canevas 'ctx.putImageData (data, 0,0)' Utiliser toDataURL est lent et utilise 2.5 fois plus de mémoire que Base64 encode 6 Bits par caractère, alors que les caractères sont 16 bits en javascript donc vous perdez 10 bits pour tous les 6 bits dans l'image. L'utilisation de 'destination-out' est correcte. – Blindman67

Répondre

1

J'avais exactement le même problème que vous, et je suis si heureux que je suis tombé sur votre question/solution, car ce fut un moment pour moi lightbulb. Dès que j'ai vu votre solution, j'ai compris ce qui se passait.

Pour donner un aperçu de la raison pour laquelle votre solution fonctionne, globalCompositeOperation est une propriété du canevas qui dicte essentiellement la manière dont les données, dans ce cas un trait, sont placées sur le canevas. Par défaut, il s'agit de source-over, qui place simplement un nouveau trait de ligne au-dessus des traits existants. Comme vous l'avez mentionné, l'effacement utilise destination-out, qui conserve tout le contenu existant où il ne chevauche pas le nouveau trait (d'où l'effacement). Pour certains schémas d'information et des explications que je recommande vivement le MDN Centre de documentation pour globalCompositeOperation: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation

Donc, si vous passez en mode d'effacement (pour vous, gomme à effacer = true), effacer, puis immédiatement essayer de défaire, le globalCompositeOperation sera toujours être réglé sur destination-out. Cela signifie que lorsque votre annulation tente de dessiner l'image stockée sur le canevas, tout va disparaître car il s'efface essentiellement (comme le dit la destination-out, il écrase tout le contenu existant où il chevauche le nouveau contenu, ce qui dans ce cas le cas est l'espace entier de la toile). Par conséquent, vous devez le redéfinir sur la source comme vous le faites dans votre solution afin que l'image restaurée apparaisse réellement sur le canevas. J'espère que cela aide!

+0

Génial! Merci pour le feedback et la ressource. – user2950222