TypeError: “undefined is not a function”
Question
So I am trying to create a custom shape using kinetic.js but I have ran into a problem. I am calling a function on click that should display a new drawing but I get the error:
Uncaught TypeError: undefined is not a function
Here is the function code:
function helpShow(){
var stage = new Kinetic.Stage({
container: 'SkateboardCanvas',
width: 800,
height: 500
});
var layer = new Kinetic.Layer();
var helpMenu = new Kinetic.Shape({
drawFunc: function(context) {
context.beginPath();
context.moveTo(600,500);
context.lineTo(600,450);
context.moveTo(200,500);
context.lineTo(600,500);
// x1, y1, x2, y2, radius
console.log(context);
context.arcTo(600,350,550,350,50);
context.lineTo(250,350);
context.moveTo(200,500);
context.lineTo(200,450);
context.arcTo(200,350,250,350,50);
context.closePath();
context.fillStrokeShape(this);
},
fill: 'rgba(255, 255, 255, 0.5)',
stroke: 'black',
strokeWidth: 4
});
layer.add(helpMenu);
console.log(layer);
console.log(stage);
stage.add(layer);
}
The line it is throwing the error on is:
context.arcTo(600,350,550,350,50);
And here is the console logs which shows everything is defined.
Kinetic.Layer {nodeType: "Layer", canvas: Kinetic.SceneCanvas, hitCanvas: Kinetic.HitCanvas, children: Kinetic.Collection[1], _id: 2…} creatorCanvas.js:86
Kinetic.Stage {nodeType: "Stage", children: Kinetic.Collection[0], _id: 1, eventListeners: Object, attrs: Object…} creatorCanvas.js:87
Kinetic.SceneContext {canvas: Kinetic.SceneCanvas, _context: CanvasRenderingContext2D, _fillColor: function, _fillPattern: function, _fillLinearGradient: function…}
Also the canvas and context is defined at the top of the JavaScript file as follows:
var canvas = $("#SkateboardCanvas");
var context = canvas.get(0).getContext("2d");
I am relatively new to it all so any help/explanation on why this is happening would be great or if I am being a complete newb I apologize.
Solution
The context you're given by the Kinetic.Shape is actually a wrapper around an actual canvas context.
The wrapper you're given does not support the path context.arcTo command.
You have several workarounds:
Refactor your shape to use context.quadraticCurveTo instead of arcTo.
Replace your Kinetic.Shape with a Kinetic.Image that uses an offscreen html canvas element as its image source. This way you can use native canvas's .arcTo command on the offscreen canvas.
Here's a demo of #2: http://jsfiddle.net/m1erickson/u69A8/
var myShape=new Kinetic.Image({
x:10,
y:10,
image:drawTab(),
});
layer.add(myShape);
layer.draw();
function drawTab(){
var canvas=document.createElement("canvas");
var context=canvas.getContext("2d");
canvas.width=400;
canvas.height=150;
context.save();
context.translate(-200,-350);
context.beginPath();
context.moveTo(600,500);
context.lineTo(600,450);
context.moveTo(200,500);
context.lineTo(600,500);
// x1, y1, x2, y2, radius
context.arcTo(600,350,550,350,50);
context.lineTo(250,350);
context.moveTo(200,500);
context.lineTo(200,450);
context.arcTo(200,350,250,350,50);
context.closePath();
context.fillStyle="red";
context.fill();
context.restore();
return(canvas);
}