11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour.
J'essaye de faire du graphisme dynamique sur un <canvas> en javascript. J'essaye d'effacer en utilisant fond.globalCompositeOperation = "source-out"; Mais ça ne fonctionne pas. J'ai du "trainage" sur ma figure en déplacement et je ne sais pas pourquoi. Une idée ?

<!DOCTYPE html>
<html lang="fr" >
<head>
<meta charset="utf-8">
</head>
<body onkeyup = "keyUp(event);" onkeydown = "keyDown(event);">

<center><h2>Test d'effacement sur un Canvas</h2></center>
<p>Lorsque vous enfoncez la touche "Ctrl" vous déclenchez la rotation de
la figure ci dessous. Normalement, à chaque petite rotation, on devrait
effacer la figure pour la redessiner. Mais ça ne fonctionne pas correctement :
la figure est dédoublée, je ne sais pas pourquoi. Suivant la valeur de la
variable "tracerCercle", le défaut apparait sur le segment ou sur le cercle ! </p>

<div id="leConteneur">
    <canvas id="layer0"></canvas> <!-- Fond  -->
</div>

<script>
"use strict" ;

var angle = 0.0 ;
var cosAngle = Math.cos (angle) ;
var sinAngle = Math.sin (angle) ;
var ctrl = false ;
// canvas graphic context
var canvas = document.getElementById("layer0") ; 
canvas.width = 600 ; 
canvas.height = 600 ;
var fond = canvas.getContext('2d'); 
fond.fillStyle = "white" ;
fond.fillRect (0, 0, 600, 600) ;
fond.strokeStyle = "black" ;
fond.lineWidth = 2 ;
var x0 = 300 ; var y0 = 300 ;
var r1 = 150 ; var r2 = 50 ;
var color = "black" ;
var tracerCercle = true ;

function keyDown (event) {
    if (event.keyCode == 17) ctrl = true ;
}

function keyUp (event) {
    if (event.keyCode == 17) ctrl = false ;
}

function draw (color) {
    fond.beginPath () ;
    fond.moveTo (x0, y0) ;
    var xc = x0 + r1 * cosAngle ;
    var yc = y0 + r1 * sinAngle ;
    fond.lineTo (xc, yc) ;
    fond.closePath() ;
    fond.stroke () ;
    if (!tracerCercle) return ;
    fond.beginPath () ;
    fond.arc (xc, yc, r2, 0, 2*Math.PI) ;
    fond.closePath() ;
    fond.stroke () ;
}

function erase (color) {
    fond.globalCompositeOperation = "source-out";
    //fond.globalCompositeOperation = "xor"; // ne fonctionne pas
    //fond.lineWidth = 4 ; // essai d'élargir le trait, c'est pire
    draw (color) ;
    fond.lineWidth = 2 ;
    fond.globalCompositeOperation = "source-over" ;
}

function animate() {
    if (ctrl) {
        erase (color) ;
        angle += Math.PI / 90 ;
        if (angle >= 2*Math.PI) angle = 0 ;
        cosAngle = Math.cos (angle) ;
        sinAngle = Math.sin (angle) ;
        draw (color) ;
    }
    requestAnimationFrame(animate) ;
}

draw (color) ;
animate () ;
</script>
</body>
</html>

Modifié par JiPe38 (04 May 2021 - 15:21)
Salut,
J'ai testé et je ferais différemment. Au lieu d'utiliser les types de fond.globalCompositeOperation je redessinerais le rectangle blanc du fond à chaque fois en fait.

    function draw(color) {
        fond.fillStyle = "white";
        fond.fillRect(0, 0, 600, 600);
        ...
        ...
    }
    function erase(color) {
        draw(color);
    }

Modifié par MatthieuR (06 May 2021 - 20:57)
Un peu en retard sur ce coup : je pensais être prévenu par email d'une réponse. Merci pour cette solution, mais je l'ai déjà essayée. Ca m'oblige à TOUT redessiner sur l'écran et c'est un peu lourd. Mais bon, pour l'instant ça fonctionne comme ça, et j'aimerais faire mieux en effaçant et redessinant que le strict nécessaire.