2016-05-05 2 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 *)», затем в разделе «РАМКИ И РАСШИРЕНИЯ» выберите jQuery, например * «jQuery 1.12.2» *. Затем нажмите «Запустить» в верхнем левом углу. –

ответ

0

Вы можете постоянно перерисовывать содержимое холста, как вы изменения размера, но есть более эффективный способ сделать это.

В качестве альтернативы ...

Непрерывно перерисовывать содержимое холста является ресурсоемким. Более эффективным способом обработки анимации масштабирования является использование CSS для этого. Когда анимация завершается, только тогда изменяет размер холста и перерисовывает содержимое на его окончательном увеличенном масштабе. Это правда, что при анимации перехода содержимое холста может временно растягиваться или сжиматься, но все происходит так быстро, что это не будет заметно.

  1. Сохранить unzoomed холст на другой холст в памяти: var memCanvas = canvas.cloneNode() & drawImage видимый холст на memCanvas.

  2. Используйте анимацию CSS для изменения размера элемента холста до размера масштабирования. Вот пример на предыдущем SO Q&A. Анимация завершается так быстро, что, вероятно, не будет заметна, если содержимое будет диспропорционально изменяться.

  3. Когда анимация завершена (размер холста полностью увеличен), вы можете масштабировать сохраненный чертеж до нового размера с помощью drawImage(savedCanvas, 0,0, originalWidth*zoomFactor, originalHeight*zoomFactor) и сбросить ширину и высоту CSS в исходный размер.

Смежные вопросы