web-dev-qa-db-fra.com

Masquage / chevauchement d'images sur toile

Dans mon projet, je dois implémenter une image couleur différente sur l'autre image de même taille et motif en utilisant la toile et les images ne sont pas en formes rondes ou rectangulaires. Ils sont tous en forme de vagues et ils s'appliqueront sur une seule image d'arrière-plan principale pour afficher plusieurs graphiques sur chaque fonction onclick.

L'image superposée doit être modifiée dans une autre couleur sélectionnée. Ma question Existe-t-il un moyen d'utiliser la toile à partir de laquelle nous pouvons changer la couleur de l'image qui est dessinée par la toile ou nous devons toujours utiliser des images différentes et appliquer avec CSS/jQuery.

J'ai lu sur le masquage et le chevauchement des images sur toile. Mais je ne peux pas comprendre avec mes images car elles ne sont pas en forme de carré ou de cercle, alors la première chose est de savoir comment je dessine plusieurs formes d'onde sur une seule image. Je n'ai aucune idée de ce que j'ai recherché, mais je ne parviens pas à rechercher la solution parfaite.

Mon besoin est simplement de dessiner une image d'onde sur la toile et de changer sa couleur à partir de la fonction de clic et également de définir une autre div avec l'image d'arrière-plan et également plus de deux toiles se chevaucheront. Est-ce possible?

(Cela signifie: Cette fonctionnalité est pour créer ou définir plusieurs graphiques sur une voiture, pour que chaque image graphique doit être définie dans une toile et pour un autre graphique doit se chevaucher sur div et la première toile)

28
Anup

Vous pouvez utiliser la composition de contexte pour remplacer une partie d'une image.

Par exemple, si vous avez déjà ce logo bleu comme image:

enter image description here

Si vous souhaitez que la partie supérieure du logo soit de couleur violette:

enter image description here

Vous pouvez utiliser le compositing pour recolorer la partie supérieure de l'image.

Tout d'abord, utilisez votre éditeur d'images préféré pour recadrer toute partie que vous ne souhaitez pas recolorer.

Ce qui reste est appelé superposition.

Cette partie de superposition de l'image est ce que nous recolorierons par programme.

enter image description here

Cette superposition peut être recoloriée par programme dans n'importe quelle couleur.

enter image description hereenter image description here

Comment la superposition a été recoloriée par programme:

  1. Dessinez la superposition sur une toile vide.
  2. Réglez le mode de composition sur "source-in".
  3. L'effet: Seuls les pixels existants sont remplacés - les pixels transparents restent transparents
  4. Dessinez maintenant un rectangle de n'importe quelle couleur recouvrant la toile
  5. (rappelez-vous, seule la superposition existante sera remplacée par la nouvelle couleur)

Comment compléter le logo avec la couleur de superposition modifiée

  1. Réglez le mode de composition sur "destination au sommet"
  2. L'effet: Seuls les pixels transparents sont remplacés - les pixels existants restent inchangés
  3. Dessinez maintenant le logo d'origine
  4. (rappelez-vous, la superposition colorée existante ne sera pas remplacée)

Cet effet de composition "destination au sommet" est parfois appelé "dessin sous".

Cette superposition peut même être remplacée par des textures!

enter image description here

Voici le code et un violon: http://jsfiddle.net/m1erickson/bfUPr/

<!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; padding:20px; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var truck,logo,overlay;
    var newColor="red";

    var imageURLs=[];
    var imagesOK=0;
    var imgs=[];
    imageURLs.Push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/boxTruck.png");
    imageURLs.Push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmall.png");
    imageURLs.Push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmallOverlay.png");
    loadAllImages();

    function loadAllImages(){
        for (var i = 0; i < imageURLs.length; i++) {
          var img = new Image();
          imgs.Push(img);
          img.onload = function(){ imagesOK++; imagesAllLoaded(); };
          img.src = imageURLs[i];
        }      
    }

    var imagesAllLoaded = function() {
      if (imagesOK==imageURLs.length ) {
         // all images are fully loaded an ready to use
         truck=imgs[0];
         logo=imgs[1];
         overlay=imgs[2];
         start();
      }
    };


    function start(){

        // save the context state
        ctx.save();

        // draw the overlay
        ctx.drawImage(overlay,150,35);

        // change composite mode to source-in
        // any new drawing will only overwrite existing pixels
        ctx.globalCompositeOperation="source-in";

        // draw a purple rectangle the size of the canvas
        // Only the overlay will become purple
        ctx.fillStyle=newColor;
        ctx.fillRect(0,0,canvas.width,canvas.height);

        // change the composite mode to destination-atop
        // any new drawing will not overwrite any existing pixels
        ctx.globalCompositeOperation="destination-atop";

        // draw the full logo
        // This will NOT overwrite any existing purple overlay pixels
        ctx.drawImage(logo,150,35);

        // draw the truck
        // This will NOT replace any existing pixels
        // The purple overlay will not be overwritten
        // The blue logo will not be overwritten
        ctx.drawImage(truck,0,0);

        // restore the context to it's original state
        ctx.restore();

    }


}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=500 height=253></canvas>
</body>
</html>
45
markE

La question telle qu'elle est actuellement est un peu floue OMI. Pour donner une réponse plus générale que vous pouvez appliquer à un scénario où vous avez besoin d'un découpage, vous pouvez utiliser (au moins) deux approches:

Méthode 1 - Utilisation du mode composite pour découper

Le mode composite est le moyen le plus simple mais aussi le moins flexible car vous devez prédéfinir le masque d'écrêtage en tant qu'image avec un fond transparent (généralement PNG).

Vous pouvez soit utiliser les parties solides de l'image pour découper la prochaine chose dessinée, soit utiliser les zones transparentes pour remplir.

Voici une approche où nous utilisons les parties solides pour découper la prochaine forme/image dessinée:

/// draw the shape we want to use for clipping
ctx1.drawImage(imgClip, 0, 0);

/// change composite mode to use that shape
ctx1.globalCompositeOperation = 'source-in';

/// draw the image to be clipped
ctx1.drawImage(img, 0, 0);

Ici, le globalCompositeOperation est changé en source-in Ce qui signifie que l'image source (celle que nous allons dessiner à côté de la destination) sera dessinée à l'intérieur le solide existant Les données. Rien ne sera dessiné dans les zones transparentes.

Si notre masque d'écrêtage ressemble à ceci (aléatoire fair-use du net):

Clip mask

Et notre image comme ça:

Main image

Le résultat sera le suivant:

Composited image

Méthode 2 - Utilisation d'un chemin pour découper

Vous pouvez également définir un chemin pour l'écrêtage. C'est très flexible car vous pouvez ajuster le chemin ou l'animer si vous le souhaitez.

Remarque: Gardez à l'esprit que l'écrêtage à l'aide de Path est actuellement un peu "fragile" dans les navigateurs, vous devriez donc envisager d'utiliser save() et restore() avant et après avoir défini et utilisé un chemin de clip comme les navigateurs ne peuvent pas réinitialiser le clip pour le moment (restore restaurera le clip par défaut = toile complète);

Permet de définir un chemin simple en zig-zag (ce seront vos vagues dans votre cas):

/// use save when using clip Path
ctx2.save();

ctx2.beginPath();
ctx2.moveTo(0, 20);
ctx2.lineTo(50,0);
/// ... more here - see demo
ctx2.lineTo(400, 20);
ctx2.lineTo(400, 100);
ctx2.lineTo(0, 100);
ctx2.closePath();

/// define this Path as clipping mask
ctx2.clip();

/// draw the image
ctx2.drawImage(img, 0, 0);

/// reset clip to default
ctx2.restore();

Maintenant que nous avons défini le masque d'écrêtage à l'aide de clip tout ce qui est dessiné sur le canevas suivant sera écrêté pour tenir à l'intérieur de cette forme (notez que nous nous assurons que la forme peut se terminer là où elle a commencé):

Path clipped image

Voir la démonstration en ligne de ces méthodes ici

52
user1693593