Canvas createPattern函数不起作用

时间:2017-08-02 21:53:44

标签: javascript html5 canvas

我有一个简单的函数,旨在使用HTML中的canvas标签更轻松地创建模式。我在嵌入了此代码的网站上有一个图像:



    <style type="text/css">
        .invisible {
            display: none;
        }
    </style>
    <img class="invisible" id="image" src="Images/test.png"></img>
&#13;
&#13;
&#13;

和我制作模式的函数是:

&#13;
&#13;
    //Function that allows you to create a pattern
    this.pattern = function(image, mode) {
        var pat = this.ctx.createPattern(image, mode);
        return pat;
    };
&#13;
&#13;
&#13;

但是当我尝试用这段代码调用函数时:

&#13;
&#13;
var testImage = document.getElementById("image");
myCanvas.fill(myCanvas.pattern(testImage, "repeat"));
&#13;
&#13;
&#13;

日志中出现错误,上面写着:

Uncaught TypeError: Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'

现在,我非常确定我输入的变量是HTMLImageElement,但错误仍然存​​在。

完整代码:

&#13;
&#13;
<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title>Canvas Library</title>
    </head>
    <style type="text/css">
        .invisible {
            display: none;
        }
    </style>
     <body>
        <p id="text">Unknown</p>
        <canvas width="400" height="400" id="canvas"></canvas>
        <script type="text/javascript" src="Canvas.js"></script>
        <img class="invisible" id="image" src="Images/test.png"></img>
        </body>

</html>
&#13;
&#13;
&#13;

&#13;
&#13;
// JavaScript File
var Canvas = document.getElementById("canvas");
var label = document.getElementById("text");
var testImage = document.getElementById("image");

var distance = function(x1, y1, x2, y2) {
    var a = Math.pow(x2 - x1, 2);
    var b = Math.pow(y2 - y1, 2);
    return Math.sqrt(a + b);
};

//Declare the Canvas Object
var canvas = function(src) {
    //Function to see if a line is colliding with a certain point Has an accuracy of about 1 pixel
    this.lineIsColliding = function(startX, startY, endX, endY, testX, testY) {
        const v1 = {
            x: endX - startX,
            y: endY - startY
        };
        const l2 = v1.x * v1.x + v1.y * v1.y;
        if (l2 === 0) {
            return false;
        } // line has no length so can't be near anything
        const v2 = {
            x: testX - startX,
            y: testY - startY
        };
        const u = (v1.x * v2.x + v1.y * v2.y) / l2;
        return u >= 0 && u <= 1 && Math.abs((v1.x * v2.y - v1.y * v2.x) / Math.sqrt(l2)) < 1;
    };

    //The Canvas to draw on
    this.src = src;
    //The context of source(used for drawing)
    this.ctx = this.src.getContext("2d");
    //The Mouse Move Function
    this.showCoordinates = function(e) {
        console.log(e);
        label.innerHTML = "<b>x: </b>" + e.offsetX + " <b>y: </b>" + e.offsetY + ", " + myCanvas.lineIsColliding(358, 277, 365, 268, e.offsetX, e.offsetY);
    };
    //Show coordinates variable
    this.showCoordinatesBool = true;
    //The boolean to tell if we should use stroke
    var useStroke = true;
    //The fill style and stroke style(can be color, pattern, or gradient)
    this.fillStyle = "#000000";
    this.strokeStyle = "#000000";
    //The Line cap style (can be butt, square, or round)
    this.lineCap = "butt";
    //The Stroke Weight (how wide the strokes are)
    this.strokeWeightVar = "default";
    //The corner style (how the corners are drawn)
    this.cornerStyle = "miter";
    //The Shadow Color
    this.shadowColorVar = "#000000";
    //The shadow Blur
    this.shadowBlurVar = 0;
    //The shadow Offsets
    this.shadowOffsetX = 0;
    this.shadowOffsetY = 0;

    //Function to set the fill style
    this.fill = function(style) {
        this.fillStyle = style;
        this.ctx.fillStyle = style;
    };

    //Function to set the stroke style
    this.stroke = function(style) {
        this.useStroke = true;
        this.strokeStyle = style;
        this.ctx.strokeStyle = style;
    };

    //Function to delete the stroke
    this.noStroke = function() {
        this.useStroke = false;
    };

    //Function to draw a rectangle
    this.rect = function(x, y, width, height) {
        this.ctx.fillRect(x, y, width, height);
        if (this.useStroke) {
            this.ctx.strokeRect(x, y, width, height);
        }

    };

    //Function to draw a corner
    this.corner = function(style, centerX, centerY, x1, y1, x2, y2) {
        this.ctx.lineJoin = style;
        this.cornerStyle = style;
        this.ctx.beginPath();
        this.ctx.moveTo(x1, y1);
        this.ctx.lineTo(centerX, centerY);
        this.ctx.lineTo(x2, y2);
        this.ctx.stroke();
    };

    //Function to draw a hollow rectangle
    this.hollowRect = function(x, y, width, height) {
        this.ctx.strokeRect(x, y, width, height);
    };

    //Function to set the canvas background 
    this.background = function(style) {
        this.fillStyle = style;
        this.ctx.fillStyle = style;
        this.ctx.fillRect(0, 0, this.src.width, this.src.height);
    };

    //Function to draw a line
    this.line = function(startX, startY, endX, endY) {
        this.ctx.beginPath();
        this.ctx.moveTo(startX, startY);
        this.ctx.lineTo(endX, endY);
        this.ctx.stroke();
    };

    //Function to change line style
    this.lineCap = function(mode) {
        this.ctx.lineCap = mode;
        this.lineCap = mode;
    };

    //Function to change stroke weight
    this.strokeWeight = function(weight) {
        this.useStroke = true;
        this.ctx.lineWidth = weight;
        this.strokeWeightVar = weight;
    };

    //Function to clear a certain area
    this.clearArea = function(x, y, width, height) {
        this.ctx.clearRect(x, y, width, height);
    };
    //Turn the show coordinate function on
    this.enableCoordinates = function() {
        this.showCoordinatesBool = true;
        this.src.addEventListener("mousemove", this.showCoordinates);
    };
    /*Shadows*/

    //Set the shadow color
    this.shadowColor = function(color) {
        this.shadowColorVar = color;
        this.ctx.shadowColor = color;
    };
    //Set the shadow blur
    this.shadowBlur = function(blur) {
        this.shadowBlurVar = blur;
        this.ctx.shadowBlur = blur;
    };
    //Set the shadow offset
    this.shadowOffset = function(offsetX, offsetY) {
        this.shadowOffsetX = offsetX;
        this.shadowOffsetY = offsetY;
        this.ctx.shadowOffsetX = offsetX;
        this.ctx.shadowOffsetY = offsetY;
    };
    //Remove shadows
    this.noShadow = function() {
        this.shadowOffset(0, 0);
        this.shadowColor("#000000");
        this.shadowBlur(0);
    };

    //Function to see if a rectangle is colliding with a specific point
    this.rectIsColliding = function(rectX, rectY, rectWidth, rectHeight, testX, testY) {
        this.ctx.rect(rectX, rectY, rectWidth, rectHeight);
        return this.ctx.isPointInPath(testX, testY);
    };
    //Function that returns a custom linear gradient
    this.linearGradient = function(startX, startY, endX, endY, colorStops) {
        var gradient = this.ctx.createLinearGradient(startX, startY, endX, endY);
        for (var i = 0; i < colorStops.length; i++) {
            gradient.addColorStop(colorStops[i].location, colorStops[i].color);
        }
        return gradient;
    };
    //Function that returns a custom radial gradient
    this.radialGradient = function(x0, y0, r0, x1, y1, r1, colorStops) {
        var radialGradientVar = this.ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
        for (var i = 0; i < colorStops.length; i++) {
            radialGradientVar.addColorStop(colorStops[i].location, colorStops[i].color);
        }
        return radialGradientVar;
    };
    //Function that allows you to create a pattern
    this.pattern = function(image, mode) {
        var pat = this.ctx.createPattern(image, mode);
        return pat;
    };
};

//The following code is for testing purposes ONLY!
{
    //Create a new canvas
    var myCanvas = new canvas(Canvas);
    //Set the Background Color
    myCanvas.background("#ff0000");
    //Set the fill color
    myCanvas.fill("#0000ff");
    //Set the Stroke Color
    myCanvas.stroke("#00ff00");
    //Draw a rectangle
    myCanvas.rect(164, 153, 50, 100);
    //Draw a hollow rectangle
    myCanvas.hollowRect(300, 300, 50, 50);
    //Disable the Stroke
    myCanvas.noStroke();
    //Draw a rectangle with no stroke
    myCanvas.rect(21, 18, 50, 50);
    //Change the Stroke color
    myCanvas.stroke("#ffff00");
    //Change the stroke weight
    myCanvas.strokeWeight(10);
    //Change the line cap
    myCanvas.lineCap("round");
    //Draw a line
    myCanvas.line(350, 30, 250, 80);
    //Draw a corner
    myCanvas.corner("miter", 50, 135, 100, 185, 100, 110);
    //Enable the Coordinates
    myCanvas.enableCoordinates();
    //Clear a space from the canvas
    myCanvas.clearArea(6, 245, 100, 100);
    //Set the Shadow Color
    myCanvas.shadowColor("black");
    //Set the shadow Blur
    myCanvas.shadowBlur(20);
    //Set the shadow offset
    myCanvas.shadowOffset(10, 0);
    //Set the stroke
    myCanvas.noStroke();
    //Set the fill color
    myCanvas.fill("orange");
    //Draw a rectangle
    myCanvas.rect(268, 167, 30, 30);
    //Remove the shadow
    myCanvas.noShadow();
    //Test if the rectangle is colliding with a specific point
    if (myCanvas.rectIsColliding(268, 167, 30, 30, 290, 170)) {
        myCanvas.fill("green");
        myCanvas.rect(358, 0, 50, 46);
    }
    else {
        myCanvas.fill("yellow");
        myCanvas.rect(362, 0, 50, 46);
    }

    //Test if a line is colliding with a certain point
    console.log("function returned: " + myCanvas.lineIsColliding(358, 277, 365, 268, 362, 271));
    if (myCanvas.lineIsColliding(358, 277, 365, 268, 362, 271)) {
        console.log("line is colliding!");
        myCanvas.line(358, 277, 365, 268);
    }
    else {
        console.log("line is not colliding!");

    }

    myCanvas.line(0, 0, 50, 10);

    //Color stop used for creating gradients
    var colorStop = function(location, color) {
        this.location = location;
        this.color = color;
    };

    console.log(distance(0, 0, 50, 10));

    myCanvas.fill(myCanvas.linearGradient(259, 77, 359, 127, [new colorStop(0.0, "green"), new colorStop(1.0, "blue")]));
    myCanvas.rect(259, 87, 100, 50);
    myCanvas.fill(myCanvas.radialGradient(309, 225, 10, 309, 225, 50, [new colorStop(0.0, "yellow"), new colorStop(1.0, "green")]));
    myCanvas.rect(259, 200, 100, 50);
    myCanvas.fill(myCanvas.pattern(testImage, "repeat"));
    myCanvas.rect(132, 81, 50, 100);
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

您必须在加载图像后运行代码。

testImage.addEventListener('load', start)

但更好的方法是从javascript创建图片,这样你就可以确定图像onload尚未发出。

var image = new Image();
image.addEventListener('load', start);
image.addEventListener('error', errorfn);

image.src = 'Images/test.png'

有工作Sample。我没有看到渲染的图案图像,但是在控制台中没有错误,并且图像肯定会加载。