2016-05-05 48 views
0

我正在设计一个油漆桶应用程序。我的代码工作正常。只需要一点帮助。在放大和缩小按钮时,我正在改变画布的高度和宽度。我如何将动画应用到它?这是我完整的代码。缩放部分在最后。您可以简单地将其粘贴到文件中。它会工作。如何用动画缩放画布

<!DOCTYPE html> 
<html> 
     <head> 
     <title>Painitng</title> 
     <style> 
body { 
    width: 100%; 
    height: auto; 
    text-align: center; 
} 
.colorpick { 
    widh: 100%; 
    height: atuo; 
} 
.pick { 
    display: inline-block; 
    width: 30px; 
    height: 30px; 
    margin: 5px; 
    cursor: pointer; 
} 
canvas { 
    border: 2px solid silver; 
} 
</style> 
     </head> 
     <body> 
<button id="zoomin">Zoom In</button> 
<button id="zoomout">Zoom Out</button> 
<button id = "undo-button" onclick="history('undo')">Undo</button> 
<button id = "redo-button" onclick="history('redo')">Redo</button> 
<div id="canvasDiv"></div> 
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script> 
<script type="text/javascript"> 
      var colorYellow = { 
       r: 255, 
       g: 207, 
       b: 51 
      }; 
      var context; 
      var canvasWidth = 500; 
      var canvasHeight = 500; 
      var myColor = colorYellow; 
      var curColor = myColor; 
      var outlineImage = new Image(); 
      var backgroundImage = new Image(); 
      var drawingAreaX = 0; 
      var drawingAreaY = 0; 
      var drawingAreaWidth = 500; 
      var drawingAreaHeight = 500; 
      var colorLayerData; 
      var outlineLayerData; 
      var totalLoadResources = 2; 
      var curLoadResNum = 0; 
      var undoarr = new Array(); 
      var redoarr = new Array(); 

      function history(command){ // handles undo/redo button events. 
      var data; 
      if(command === "redo"){ 
       data = historyManager.redo(); // get data for redo 
      }else 
      if(command === "undo"){ 
       data = historyManager.undo(); // get data for undo 
      } 
      if(data !== undefined){ // if data has been found 
       setColorLayer(data); // set the data 
      } 
     } 

     // sets colour layer and creates copy into colorLayerData 
     function setColorLayer(data){ 
      context.putImageData(data, 0, 0); 
      colorLayerData = context.getImageData(0, 0, canvasWidth, canvasHeight); 
      context.drawImage(backgroundImage, 0, 0, canvasWidth, canvasHeight); 
      context.drawImage(outlineImage, 0, 0, drawingAreaWidth, drawingAreaHeight);    
     } 

      // Clears the canvas. 
      function clearCanvas() { 
       context.clearRect(0, 0, context.canvas.width, context.canvas.height); 
      } 



      // Draw the elements on the canvas 
      function redraw() { 
       uc = 0; 
       rc = 0; 
       var locX, 
         locY; 

       // Make sure required resources are loaded before redrawing 
       if (curLoadResNum < totalLoadResources) { 
        return; // To check if images are loaded successfully or not. 
       } 

       clearCanvas(); 
       // Draw the current state of the color layer to the canvas 
       context.putImageData(colorLayerData, 0, 0); 

       historyManager.push(context.getImageData(0, 0, canvasWidth, canvasHeight)); 
       redoarr = new Array(); 
       // Draw the background 
       context.drawImage(backgroundImage, 0, 0, canvasWidth, canvasHeight); 

       // Draw the outline image on top of everything. We could move this to a separate 
       // canvas so we did not have to redraw this everyime. 
       context.drawImage(outlineImage, 0, 0, drawingAreaWidth, drawingAreaHeight); 


      } 
      ; 

      function matchOutlineColor(r, g, b, a) { 

       return (r + g + b < 100 && a === 255); 
      } 
      ; 

      function matchStartColor(pixelPos, startR, startG, startB) { 

       var r = outlineLayerData.data[pixelPos], 
         g = outlineLayerData.data[pixelPos + 1], 
         b = outlineLayerData.data[pixelPos + 2], 
         a = outlineLayerData.data[pixelPos + 3]; 

       // If current pixel of the outline image is black 
       if (matchOutlineColor(r, g, b, a)) { 
        return false; 
       } 

       r = colorLayerData.data[pixelPos]; 
       g = colorLayerData.data[pixelPos + 1]; 
       b = colorLayerData.data[pixelPos + 2]; 

       // If the current pixel matches the clicked color 
       if (r === startR && g === startG && b === startB) { 
        return true; 
       } 

       // If current pixel matches the new color 
       if (r === curColor.r && g === curColor.g && b === curColor.b) { 
        return false; 
       } 

       return true; 
      } 
      ; 

      function colorPixel(pixelPos, r, g, b, a) { 
       colorLayerData.data[pixelPos] = r; 
       colorLayerData.data[pixelPos + 1] = g; 
       colorLayerData.data[pixelPos + 2] = b; 
       colorLayerData.data[pixelPos + 3] = a !== undefined ? a : 255; 
      } 
      ; 

      function floodFill(startX, startY, startR, startG, startB) { 
       var newPos, 
         x, 
         y, 
         pixelPos, 
         reachLeft, 
         reachRight, 
         drawingBoundLeft = drawingAreaX, 
         drawingBoundTop = drawingAreaY, 
         drawingBoundRight = drawingAreaX + drawingAreaWidth - 1, 
         drawingBoundBottom = drawingAreaY + drawingAreaHeight - 1, 
         pixelStack = [[startX, startY]]; 

       while (pixelStack.length) { 

        newPos = pixelStack.pop(); 
        x = newPos[0]; 
        y = newPos[1]; 

        // Get current pixel position 
        pixelPos = (y * canvasWidth + x) * 4; 

        // Go up as long as the color matches and are inside the canvas 
        while (y >= drawingBoundTop && matchStartColor(pixelPos, startR, startG, startB)) { 
         y -= 1; 
         pixelPos -= canvasWidth * 4; 
        } 

        pixelPos += canvasWidth * 4; 
        y += 1; 
        reachLeft = false; 
        reachRight = false; 

        // Go down as long as the color matches and in inside the canvas 
        while (y <= drawingBoundBottom && matchStartColor(pixelPos, startR, startG, startB)) { 
         y += 1; 

         colorPixel(pixelPos, curColor.r, curColor.g, curColor.b); 

         if (x > drawingBoundLeft) { 
          if (matchStartColor(pixelPos - 4, startR, startG, startB)) { 
           if (!reachLeft) { 
            // Add pixel to stack 
            pixelStack.push([x - 1, y]); 
            reachLeft = true; 
           } 

          } else if (reachLeft) { 
           reachLeft = false; 
          } 
         } 

         if (x < drawingBoundRight) { 
          if (matchStartColor(pixelPos + 4, startR, startG, startB)) { 
           if (!reachRight) { 
            // Add pixel to stack 
            pixelStack.push([x + 1, y]); 
            reachRight = true; 
           } 
          } else if (reachRight) { 
           reachRight = false; 
          } 
         } 

         pixelPos += canvasWidth * 4; 
        } 
       } 
      } 
      ; 

      // Start painting with paint bucket tool starting from pixel specified by startX and startY 
      function paintAt(startX, startY) { 

       var pixelPos = (startY * canvasWidth + startX) * 4, 
         r = colorLayerData.data[pixelPos], 
         g = colorLayerData.data[pixelPos + 1], 
         b = colorLayerData.data[pixelPos + 2], 
         a = colorLayerData.data[pixelPos + 3]; 

       if (r === curColor.r && g === curColor.g && b === curColor.b) { 
        // Return because trying to fill with the same color 
        return; 
       } 

       if (matchOutlineColor(r, g, b, a)) { 
        // Return because clicked outline 
        return; 
       } 

       floodFill(startX, startY, r, g, b); 

       redraw(); 
      } 
      ; 

      // Add mouse event listeners to the canvas 
      function createMouseEvents() { 

       $('#canvas').mousedown(function (e) { 

        // Mouse down location 
        var mouseX = e.pageX - this.offsetLeft, 
          mouseY = e.pageY - this.offsetTop; 

        // assuming that the mouseX and mouseY are the mouse coords. 
        if(this.style.width){ // make sure there is a width in the style 
        // (assumes if width is there then height will be too 
         var w = Number(this.style.width.replace("px","")); // warning this will not work if size is not in pixels 
         var h = Number(this.style.height.replace("px","")); // convert the height to a number 
         var pixelW = this.width; // get the canvas resolution 
         var pixelH = this.height; 
         mouseX = Math.floor((mouseX/w) * pixelW); // convert the mouse coords to pixel coords 
         mouseY = Math.floor((mouseY/h) * pixelH); 
        } 

        if ((mouseY > drawingAreaY && mouseY < drawingAreaY + drawingAreaHeight) && (mouseX <= drawingAreaX + drawingAreaWidth)) { 
         paintAt(mouseX, mouseY); 
        } 
       }); 
      } 
      ; 

      resourceLoaded = function() { 

       curLoadResNum += 1; 
       //if (curLoadResNum === totalLoadResources) { 
       createMouseEvents(); 
       redraw(); 
       //} 
      }; 

      var historyManager = (function(){ // Anon for private (closure) scope 
      var uBuffer = []; // this is undo buff 
      var rBuffer = []; // this is redo buff 
      var currentState = undefined; // this holds the current history state 
      var undoElement = undefined; 
      var redoElement = undefined; 
      var manager = { 
       UI : { // UI interface just for disable and enabling redo undo buttons 
        assignUndoButton : function(element){ 
         undoElement = element; 
         this.update(); 
        }, 
        assignRedoButton : function(element){ 
         redoElement = element; 
         this.update(); 
        }, 
        update : function(){ 
         if(redoElement !== undefined){ 
          redoElement.disabled = (rBuffer.length === 0); 
         } 
         if(undoElement !== undefined){ 
          undoElement.disabled = (uBuffer.length === 0);         
         } 
        } 
       }, 
       reset : function(){ 
        uBuffer.length = 0; 
        rBuffer.length = 0; 
        currentState = undefined; 
        this.UI.update(); 
       }, 
       push : function(data){ 

        if(currentState !== undefined){ 
         var same=true 
         for(i=0;i<data.data.length;i++){ 
          if(data.data[i] !== currentState.data[i]){ 
           same = false;break; 
          } 
         } if(same){ 
          return; 
         } 
        } 

        if(currentState !== undefined){ 
         uBuffer.push(currentState);       
        } 
        currentState = data; 
        rBuffer.length = 0; 
        this.UI.update(); 
       }, 
       undo : function(){ 
        if(uBuffer.length > 0){ 
         if(currentState !== undefined){ 
          rBuffer.push(currentState);       
         } 
         currentState = uBuffer.pop(); 
        } 
        this.UI.update(); 
        return currentState; // return data or unfefined 
       }, 
       redo : function(){ 
        if(rBuffer.length > 0){ 
         if(currentState !== undefined){ 
          uBuffer.push(currentState);       
         } 
         currentState = rBuffer.pop(); 
        } 
        this.UI.update();  
        return currentState; 
       }, 
      } 
      return manager; 
     })(); 

      function start() { 

       var canvas = document.createElement('canvas'); 
       canvas.setAttribute('width', canvasWidth); 
       canvas.setAttribute('height', canvasHeight); 
       canvas.setAttribute('id', 'canvas'); 
       document.getElementById('canvasDiv').appendChild(canvas); 

       if (typeof G_vmlCanvasManager !== "undefined") { 
        canvas = G_vmlCanvasManager.initElement(canvas); 
       } 
       context = canvas.getContext("2d"); 
       backgroundImage.onload = resourceLoaded(); 
       backgroundImage.src = "images/t1.png"; 

       outlineImage.onload = function() { 
        context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight); 

        try { 
         outlineLayerData = context.getImageData(0, 0, canvasWidth, canvasHeight); 
        } catch (ex) { 
         window.alert("Application cannot be run locally. Please run on a server."); 
         return; 
        } 
        clearCanvas(); 
        colorLayerData = context.getImageData(0, 0, canvasWidth, canvasHeight); 
        resourceLoaded(); 
       }; 
       outlineImage.src = "images/d.png"; 
      } 
      ; 

      if(historyManager !== undefined){ 
       // only for visual feedback and not required for the history manager to function. 
       historyManager.UI.assignUndoButton(document.querySelector("#undo-button")); 
       historyManager.UI.assignRedoButton(document.querySelector("#redo-button")); 
      } 

      getColor = function() { 

      }; 

     </script> 
<script type="text/javascript"> $(document).ready(function() { 
       start(); 
      });</script> 
<script language="javascript"> 
      $('#zoomin').click(function() { 
       if ($("#canvas").width()==500){ 
       $("#canvas").width(750); 
       $("#canvas").height(750); 
       var ctx = canvas.getContext("2d"); 
       ctx.drawImage(backgroundImage, 0, 0, 749, 749); 
       ctx.drawImage(outlineImage, 0, 0, 749, 749); 
       redraw(); 
       } else if ($("#canvas").width()==750){ 

       $("#canvas").width(1000); 
       $("#canvas").height(1000); 
       var ctx = canvas.getContext("2d"); 
       ctx.drawImage(backgroundImage, 0, 0, 999, 999); 
       ctx.drawImage(outlineImage, 0, 0, 999, 999); 
       redraw(); 
       } 
      }); 
      $('#zoomout').click(function() { 
       if ($("#canvas").width() == 1000) { 

       $("#canvas").width(750); 
       $("#canvas").height(750); 
       var ctx = canvas.getContext("2d"); 
       ctx.drawImage(backgroundImage, 0, 0, 749, 749); 
       ctx.drawImage(outlineImage, 0, 0, 749, 749); 
       redraw(); 
       } else if ($("#canvas").width() == 750) { 

       $("#canvas").width(500); 
       $("#canvas").height(500); 
       var ctx = canvas.getContext("2d"); 
       ctx.drawImage(backgroundImage, 0, 0, 499, 499); 
       ctx.drawImage(outlineImage, 0, 0, 499, 499); 
       redraw(); 
       } 
      }); 
     </script> 
<div class="colorpick"> 
      <div class="pick" style="background-color:rgb(150, 0, 0);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(0, 0, 152);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(0, 151, 0);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(255, 0, 5);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(255, 255, 0);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(0, 255, 255);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(255, 0, 255);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(255, 150, 0);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(255, 0, 150);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(0, 255, 150);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(150, 0, 255);" onclick="hello(this.style.backgroundColor);"></div> 
      <div class="pick" style="background-color:rgb(0, 150, 255);" onclick="hello(this.style.backgroundColor);"></div> 
     </div> 
<script> 
      function hello(e) { 
       var rgb = e.replace(/^(rgb|rgba)\(/, '').replace(/\)$/, '').replace(/\s/g, '').split(','); 
       myColor.r = parseInt(rgb[0]); 
       myColor.g = parseInt(rgb[1]); 
       myColor.b = parseInt(rgb[2]); 
       curColor = myColor; 
      } 
     </script> 
</body> 
</html> 
+0

请注意,您可以将其设置为堆栈片段或小提琴,以便我们可以立即查看和修改代码。还有,如何使用jquery的['animate()'](http://api.jquery.com/animate/)方法? –

+0

我不知道如何创建小提琴。你能帮助我吗?是的,我试图动画(),但它没有按预期工作。 –

+0

转到:https://jsfiddle.net/。将CSS代码复制到CSS部分(右上角),对于HTML和JS也是如此。然后在jQuery中选择“Javascript(* gear *)”,然后在* FRAMEWORKS&EXTENSIONS下选择jQuery,例如*“jQuery 1.12.2”*。然后点击左上角的*运行*。 –

回答

0

为你调整你可以不断地重新绘制在画布上的内容,但有一个更有效的方式来做到这一点。

或者...

不断重绘画布内容是资源密集型的。处理缩放动画的更有效方法是使用CSS来完成。当动画完成时,只有调整画布大小并以其最终缩放比例重新绘制内容。的确,虽然动画过渡的画布内容可能会暂时出现拉伸或挤压,但这一切发生得如此之快以至于不会引人注意。

  1. 保存未缩放画布另一个内存帆布:var memCanvas = canvas.cloneNode() & drawImage可见画布的memCanvas。

  2. 使用CSS动画将画布元素调整为缩放大小。这是以前的SO Q&A的一个例子。动画完成得如此之快,如果内容不成比例调整大小,它可能不会引人注目。

  3. 动画完成后(画布处于全缩放大小),可以使用drawImage(savedCanvas, 0,0, originalWidth*zoomFactor, originalHeight*zoomFactor)将保存的图形缩放为新大小,并将CSS宽度和高度重置为原始大小。