2017-08-02 29 views
1

我有一個簡單的函數,旨在使用HTML中的畫布標籤創建模式更容易。我有嵌入該代碼在網站上的圖像:畫布createPattern函數不工作

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

和我的功能,使一個模式是這樣的:

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

但是當我嘗試用此代碼調用該函數:

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

似乎是說,這在日誌中的錯誤:

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變量,但錯誤的是還在那兒。

全碼:

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

// 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); 
 
}

+1

當您的腳本執行時''不被解析,因此不在DOM中。因此,document.getElementBy('image')將返回null。只有當頁面已經加載(最好)時,才執行腳本,或者將它插入到你的html標記的底部(但是你將不得不等待你的圖像能夠從它創建一個模式)。 – Kaiido

回答

0

你有你的圖像加載後運行代碼。

testImage.addEventListener('load', start) 

但更好的辦法是從JavaScript創建圖像,因此您可以確保圖像onload has't尚未發出。

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

image.src = 'Images/test.png' 

有工作Sample。我沒有看到渲染模式圖像,但是無論是控制檯中的錯誤還是該圖像都無法加載。

+0

我插入此代碼: //允許您創建圖案的功能 this.pattern = function(image,mode){ image.onload = function(){ var pat = this.ctx.createPattern(image,模式); return pat; }; };另一個錯誤提出說:Uncaught TypeError:Canvas.pattern(Canvas.js:191) Canvas.js:279不能設置爲'null'的屬性'onload'對不起,但我不知道如何格式化評論。 – Ptolemy2002

+0

你能準備[JSfiddle示例](https://jsfiddle.net/)嗎? – Firanolfind

+0

順便說一句我更新了答案,試試這個解決方案。 – Firanolfind