繁体   English   中英

如何用动画缩放画布

[英]How to zoom canvas with animation

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

<!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>

您可以在调整大小时不断重画画布内容 ,但是有一种更有效的方法。

或者...

不断重画画布内容会占用大量资源。 处理缩放动画的一种更有效的方法是使用CSS。 动画完成后, 调整画布的大小并以其最终缩放比例重新绘制内容。 的确,在为过渡设置动画时,画布内容可能会暂时显示为拉伸或挤压,但是所有操作如此迅速以至于不会引起注意。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM