I have multiple canvas elements which appear dynamically on my page based on VB code.
This is what my aspx page looks like:
<canvas id="canvasnhlrc" width="225" height="200" runat="server"></canvas>
<canvas id="canvascwl" width="225" height="200" runat="server"></canvas>
<canvas id="canvashslanguages" width="225" height="200" runat="server"></canvas>
This is what my aspx.vb code looks like:
canvasnhlrc.Visible = False
canvascwl.Visible = False
canvashslanguages.Visible = False
If RouteData.Values("mediasubType") IsNot Nothing Then
Dim qsubMedia As String = RouteData.Values("mediasubType")
Select Case qsubMedia
Case "nhlrc"
canvasnhlrc.Visible = True
Case "cwl"
canvascwl.Visible = True
Case "hslanguages"
canvashslanguages.Visible = True
End Select
End If
So, if my page is example.com/nhlrc, then the canvas is generated as
<canvas id="ContentPlaceHolder2_canvasnhlrc" width="225" height="200"></canvas>
Accordingly, I have formatted my js file as follows:
function init()
{
var w1 = document.getElementById('ContentPlaceHolder2_canvasnhlrc')
var w1x = w1.getContext('2d');
w1x.shadowOffsetX = 0;
w1x.shadowOffsetY = 0;
w1x.shadowBlur = 20;
w1x.shadowColor = "rgba(0, 0, 0, 0.75)";
w1x.fillStyle = 'rgb(218, 233, 246)';
w1x.beginPath();
w1x.moveTo(25, 25);
w1x.lineTo(175, 25);
w1x.lineTo(175, 50);
w1x.lineTo(200, 75);
w1x.lineTo(175, 100);
w1x.lineTo(175, 175);
w1x.lineTo(25, 175);
w1x.closePath();
w1x.fill();
var w2 = document.getElementById('ContentPlaceHolder2_canvascwl')
var w2x = w2.getContext('2d');
w2x.shadowOffsetX = 0;
w2x.shadowOffsetY = 0;
w2x.shadowBlur = 20;
w2x.shadowColor = "rgba(0, 0, 0, 0.75)";
w2x.fillStyle = 'rgb(12, 64, 114)';
w2x.beginPath();
w2x.moveTo(25, 25);
w2x.lineTo(175, 25);
w2x.lineTo(175, 50);
w2x.lineTo(200, 75);
w2x.lineTo(175, 100);
w2x.lineTo(175, 175);
w2x.lineTo(25, 175);
w2x.closePath();
w2x.fill();
var w3 = document.getElementById('ContentPlaceHolder2_canvashslanguages')
var w3x = w3.getContext('2d');
w3x.shadowOffsetX = 0;
w3x.shadowOffsetY = 0;
w3x.shadowBlur = 20;
w3x.shadowColor = "rgba(0, 0, 0, 0.75)";
w3x.fillStyle = 'rgb(12, 64, 114)';
w3x.beginPath();
w3x.moveTo(25, 25);
w3x.lineTo(175, 25);
w3x.lineTo(175, 50);
w3x.lineTo(200, 75);
w3x.lineTo(175, 100);
w3x.lineTo(175, 175);
w3x.lineTo(25, 175);
w3x.closePath();
w3x.fill();
}
onload = init;
Sadly, I can only get the first canvas element (NHLRC) to appear while the subsequent canvases (example.com/cwl, etc.) do not render. There is nothing wrong with the code because when I comment out the other two elements in the JS code, it works fine, so what am I missing, doing wrong, or what's conflicting that's not allowing each of the canvas elements to render in its corresponding page?
Your init function has too many responsibilities (find, verify and draw) * 3 .
When any one of those responsibilities meets with a failure, i.e. can't find an element, the show stops. In your case w1, w2, w3 will only be defined in their respective pages, not for every page.
You can simplify it as below:
function draw(theCanvasEl, theFill)
{
var w1x = theCanvasEl.getContext('2d');
w1x.shadowOffsetX = 0;
w1x.shadowOffsetY = 0;
w1x.shadowBlur = 20;
w1x.shadowColor = "rgba(0, 0, 0, 0.75)";
w1x.fillStyle = theFill;
w1x.beginPath();
w1x.moveTo(25, 25);
w1x.lineTo(175, 25);
w1x.lineTo(175, 50);
w1x.lineTo(200, 75);
w1x.lineTo(175, 100);
w1x.lineTo(175, 175);
w1x.lineTo(25, 175);
w1x.closePath();
w1x.fill();
}
function init()
{
var canvases = [['ContentPlaceHolder2_canvasnhlrc', 'rgb(218, 233, 246)'],
['ContentPlaceHolder2_canvascwl', 'rgb(12, 64, 114)'],
['ContentPlaceHolder2_canvashslanguages', 'rgb(12, 64, 114)']];
for(var i=0;i<canvases.length;i++)
{
var theCanvas = document.getElementById(canvases[i][0]);
if (theCanvas!=null) {
draw(theCanvas, canvases[i][1]);
break;
}
}
}
onload = init;
Related
I want to display the content of a canvas as the background of another canvas and draw a bunch of rectangles on there. I need to dynamically change:
the canvas from which to load the background image for my finalcanvas
which rectangles to draw
It's easiest if I start this process from scratch. I have imitated starting from scratch with a simple button. However, after redrawing my canvas, previous information from fabric.js remains present after dragging an item of a canvas a bit. This means that the old canvas was not cleared properly. I tried playing around with .clear() and .depose(), but to no avail.
In case the description is vague, here an image:
And an small reproducible example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js" type="text/javascript"></script>
<script>
function load_plane_onto_active_canvas() {
var c = document.getElementById('backgroundcanvas');
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
var canvas = new fabric.Canvas('finalcanvas', {
width: 333,
height: 333
});
canvas.setBackgroundImage(bg, canvas.renderAll.bind(canvas));
canvas.on("mouse:over", function(e) {
console.log(e.target)
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: 'green',
})
canvas.add(rect);
}
}
}
window.onload = function() {
// fill the background canvas with red
(function() {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
}())
load_plane_onto_active_canvas()
}
</script>
<button onclick="load_plane_onto_active_canvas()">click me</button>
</body>
</html>
I hope someone can help me!
Notice that you're creating a new instance of fabric.Canvas in your load_plane_onto_active_canvas() function. So when you're clicking the button, the existing canvases stay intact, and you're actually calling clear() on your freshly created canvas. The DOM becomes messed up at this point, with several nested canvases inside of each other - you can take a peek at the DOM inspector to see that.
What you can do instead is create the canvas instance just once, then work with a reference to it later in your other functions.
const finalCanvas = new fabric.Canvas("finalcanvas", {
width: 333,
height: 333
});
// finalCanvas now exists in the global (window) scope
function load_plane_onto_active_canvas() {
var c = document.getElementById("backgroundcanvas");
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
finalCanvas.clear();
finalCanvas.setBackgroundImage(bg, finalCanvas.renderAll.bind(finalCanvas));
finalCanvas.on("mouse:over", function (e) {
// console.log(e.target);
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: "green"
});
finalCanvas.add(rect);
}
}
}
window.onload = function () {
// fill the background canvas with red
(function () {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
})();
load_plane_onto_active_canvas();
};
document.querySelector("#b1").onclick = () => load_plane_onto_active_canvas();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.js"></script>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<button id="b1">start from scratch</button>
Can anybody help me with clearInterval? I have been working with it for hours and can't seem to get it to work. I am using a very similar code to what I found on W3 schools as follows:
Here is also a link to see in action: http://hyque.com/ani/drawImageBtn.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>DrawImage with Buttons</title>
</head>
<body>
<button id="startBtn">Start</button>
<button id="stopBtn">Stop</button><br />
<canvas id="myCanvas" width="125" height="187" style="border:1px solid #d3d3d3;">
<script>
window.onload = function() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://hyque.com/ani/adam.png";
var xPos = 0;
ctx.drawImage(img, 0, 0, 120, 182, 0, 0, 120, 182);
var el = document.getElementById('startBtn');
el.addEventListener('click', strt, false);
var el2 = document.getElementById('stopBtn');
el2.addEventListener('click', stopIt, false);
function imageXPosition() {
ctx.clearRect(0, 0, 120, 182); // This clears the canvas
ctx.drawImage(img, xPos, 0, 120, 182, 0, 0, 120, 182); //Draws the individual frames
xPos += 120; //adds the width
//This adds 1 to the second frame
if(xPos == 120){
xPos += 1;
}
if(xPos > 841){xPos = 0;} // This resets to 0 after the las frame
}
function strt(){
var intStp = setInterval(imageXPosition, 200);
}
function stopIt(){
clearInterval(intStp);
}
}
</script>
</body>
</html>
You may have a look at scoping:
var intStp;
function strt(){
intStp = setInterval(imageXPosition, 200);
}
function stopIt(){
clearInterval(intStp);
}
A variable inside of a function only exists until the function ended, unless it isnt bound to inner functions (see Closure).
function(){
var a;//a is declared
}
//a is deleted
And functions cannot access other functions properties, unless it is accessing a variable of an outer function.
You may read on MDN : JS Scoping, Functions, Variables (mainly : the basics)
IntStp variable in local scope start function. Just omit the var keyword
I have a canvas script, with a dynamic of data. I want to add a link to share the website to facebook:
https://gyazo.com/c1fd1fe956fddba27b48907dc0e9de0a
The icons are part of the image I have not generated them via canvas, now if I listen for a click for co-ords it won't work because it'll look for clicks on the first canvas part aswell.... How can I go about making those icons part of the image clickable....
Part that makes the menu:
ig.module("game.entities.gameover").requires("impact.entity", "game.entities.button-gameover").defines(function() {
var b = new ig.Timer;
EntityGameover = ig.Entity.extend({
size: {
x: 302,
y: 355
},
type: ig.Entity.TYPE.B,
animSheet: new ig.AnimationSheet("media/graphics/game/gameover.png", 301, 352),
zIndex: 900,
globalAlpha: 0.1,
closeDialogue: !0,
init: function(c, d, g) {
this.parent(c, d, g);
this.addAnim("idle", 1, [0]);
this.currentAnim = this.anims.idle;
this.tween({
pos: {
x: 89,
y: 120
}
}, 0.5, {
easing: ig.Tween.Easing.Back.EaseInOut
}).start();
this.storage = new ig.Storage;
this.storage.initUnset("highscore-CTF", 0);
this.storage.initUnset("highscore-CTF2", 0);
this.storage.initUnset("highscore-CTF3", 0);
ig.global.score > this.storage.get("highscore-CTF") ? (this.storage.set("highscore-CTF3", this.storage.get("highscore-CTF2")), this.storage.set("highscore-CTF2", this.storage.get("highscore-CTF")), this.storage.set("highscore-CTF", ig.global.score), this.storage.initUnset("highscore-CTF2", 0), this.storage.initUnset("highscore-CTF3", 0)) : ig.global.score > this.storage.get("highscore-CTF2") ?
(this.storage.set("highscore-CTF3", this.storage.get("highscore-CTF2")), this.storage.set("highscore-CTF2", ig.global.score), this.storage.initUnset("highscore-CTF2", 0), this.storage.initUnset("highscore-CTF3", 0)) : ig.global.score > this.storage.get("highscore-CTF3") && this.storage.set("highscore-CTF3", ig.global.score);
this.storage.initUnset("total-CTF", 0);
this.storage.set("total-CTF", this.storage.get("total-CTF") + ig.global.score);
ig.game.spawnEntity(EntityButtonGameover, 23, 700, {
buttonID: 1
});
ig.game.spawnEntity(EntityButtonGameover,
220, 700, {
buttonID: 2
});
ig.game.spawnEntity(EntityButtonGameover, 390, 700, {
buttonID: 3
});
b.set(0.3)
},
update: function() {
this.parent()
},
draw: function() {
this.ctx = ig.system.context;
this.closeDialogue ? (this.ctx.save(), this.ctx.fillStyle = "#000000", this.ctx.globalAlpha = this.globalAlpha, this.ctx.fillRect(0, 0, 480, 640), this.ctx.restore(), this.globalAlpha = 0.7 <= this.globalAlpha ? 0.7 : this.globalAlpha + 0.01) : this.closeDialogue || (this.ctx.save(), this.ctx.fillStyle = "#000000", this.ctx.globalAlpha = this.globalAlpha, this.ctx.fillRect(0,
0, 480, 640), this.ctx.restore(), this.globalAlpha = 0.1 >= this.globalAlpha ? 0 : this.globalAlpha - 0.05);
this.parent();
this.ctx.font = "30px happy-hell";
this.ctx.fillStyle = "#5b2a0b";
this.ctx.textAlign = "center";
this.ctx.fillText(_STRINGS.UI.Best, this.pos.x + 70, this.pos.y + 180);
this.ctx.fillText(_STRINGS.UI.Score, this.pos.x + 70, this.pos.y + 260);
//share
this.ctx.font = "30px happy-hell";
this.ctx.fillStyle = "#ffffff";
this.ctx.textAlign = "left";
this.ctx.fillText(this.storage.getInt("highscore-CTF"), this.pos.x + 140, this.pos.y + 180);
this.ctx.fillText(ig.global.score, this.pos.x + 140, this.pos.y + 260)
},
closeDialogueFunc: function() {
this.closeDialogue && (this.tween({
pos: {
x: 89,
y: -600
}
}, 0.5, {
easing: ig.Tween.Easing.Back.EaseInOut
}).start(), this.closeDialogue = !1)
}
})
});
A simple, versatile way to add menus to canvas graphics is to simply overlay an absolutely positioned DOM structure. Your browser has already all event handling build-in, there is no need to reinvent the wheel.
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(0, 155, 255)';
ctx.fillRect(0, 0, canvas.width, canvas.height)
#container {
position: relative;
display: inline-block;
}
#menu {
position: absolute;
text-align: center;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
#menu a {
padding: 15px;
font-size: 50px;
line-height: 100px;
color: black;
text-shadow: 2px 2px 5px white;
}
#menu a:hover {
color: white;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" />
<div id='container'>
<canvas id='canvas' width='400' height='100'></canvas>
<div id='menu'>
<a href='http://facebook.com'><i class='fa fa-facebook-official'></i></a>
<a href='http://twitter.com'><i class='fa fa-twitter'></i></a>
<a href='http://whatsapp.com'><i class='fa fa-whatsapp'></i></a>
</div>
</div>
Your browser is capable of rendering such overlay menus very quickly. You should use CSS to style your overlay menu links or buttons.
I have managed to click on a certain element in a canvas.
I have tried to explain with comments what it does.
I have made 3 limits as shown in the image below.
And I'm comparing only with x value, if it's in between these limits. It can be more complex so getCursorPosition() method returns an object with x and y components, just in case if you need to make more comparisons.
https://jsfiddle.net/_jserodio/asa10pye/
var canvas;
var ctx;
// first get your canvas
canvas = document.getElementById('canvas');
canvas.width = 253;
canvas.heigth = 68;
// assign the context
ctx = canvas.getContext("2d");
// asign click event to the canvas
addEventListener("click", listener, false);
function listener(e) {
// if you have 3 buttons
var position = getCursorPosition(e);
var limit1 = canvas.width / 3;
//console.log("limit1: " + limit1);
var limit2 = canvas.width * 2 / 3;
//console.log("limit2: " + limit2);
var limit3 = canvas.width;
//console.log("limit3: " + limit3);
if (position.x < limit1) {
console.log("go to facebook");
//window.open("http://www.facebook.com");
} else if (position.x < limit2) {
console.log("go to twitter");
//window.open("http://www.twitter.com");
} else if (position.x < limit3) {
console.log("go to whatsapp");
//window.open("http://www.whatsapp.com");
}
//console.log("\nx" + position.x);
//console.log("y" + position.y);
}
function getCursorPosition(event) {
var rect = canvas.getBoundingClientRect();
var x = event.clientX - rect.left;
var y = event.clientY - rect.top;
var data = {
x: x,
y: y
};
return data;
}
// load image from data url
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(this, 0, 0);
};
imageObj.src = 'https://justpaste.it/files/justpaste/d307/a11791570/file1.png';
<canvas id='canvas' width="253" height="68">
</canvas>
Bonus!
Here you have a demo I made using this. demo (Draughts/checkers).
You can check the entire code here if you want.
You have several operations in this case.
Option 1:
You'll need to remember the "bounding area" of the three buttons. Anytime the canvas receives a "click", get the click position (How do I get the coordinates of a mouse click on a canvas element?). Once you get the click position. Detect if said click occurs within the bounding area of the button. If it does, use window.open to go there.
Option 2: Similar to Option 1, but instead of remembering a "bounding area", create a separate hidden canvas of the same size as your image with the backgrounds black ('#000000') and the button given distinctive colors (for example, red for Facebook, green for Twitter, and blue for Hangout?).
Then, similar to Option 1, get the click position relative to the canvas. Then use ctx.getImageData(sx, sy, sw, sh) on the context of the hidden canvas layer. If the value you get back is red, then user clicked on Facebook, if green, Twitter, and if blue, Hangout.
This is my canvas image text editor and I want to add a background image and an image that can drag and drop. I found code snippets to do things like that but with my code it is somewhat not working.
Code here
<style>canvas{width:450px; height:350px;}</style>
<canvas width="792" height="612"></canvas>
<a id="canvas-download" download="canvas-image.png" href="">Download</a>
<input type="file" id="bgload" name="bgload" />
<input type="file" id="logoload" name="logoload" />
<input id="title" value="[Certificate Title]"/>
<input id="present" value="[Presented to]" />
<input id="receiver" value="[Type Name Here]" />
<input id="awardDate" value="[Awarding Date]" />
<input id="signature" value="[Signature]" />
<script>
$(function () {
var cvs = $("canvas"),
cvsWidth = 792,
cvsHeight = 612,
ctx = cvs[0].getContext("2d"),
title = $("#title"),
present = $("#present"),
receiver = $("#receiver"),
awardDate = $("#awardDate"),
signature = $("#signature");
function writeCaption(text, y, size, x) {
var size = size;
do {
size--;
ctx.font = size + 'px Georgia';
ctx.lineWidth = size / 32;
} while (ctx.measureText(text).width > cvsWidth)
if (x == 0)
ctx.fillText(text, cvsWidth / 2, y);
else
ctx.fillText(text, x, y);
//ctx.strokeText(text, cvsWidth / 2, y);
}
// Setup basic canvas settings
$.extend(ctx, {
//strokeStyle: "#000000",
textAlign: 'center',
fillStyle: "#000",
lineCap: "round"
})
$("<img />")
.load(function () {
var img = this;
$(document.body).on("keyup", function () {
var titleText = title.val(),
presentText = present.val(),
signatureText = signature.val(),
awardDateText = awardDate.val(),
receiverText = receiver.val();
ctx.clearRect(0, 0, cvsWidth, cvsHeight);
ctx.drawImage(img, 0, 0, cvsWidth, cvsHeight);
//text alignments
ctx.textBaseline = 'top';
writeCaption(titleText, 150, 40, 0);
ctx.textBaseline = 'top';
writeCaption(presentText, 240, 20, 0);
ctx.textBaseline = 'top';
writeCaption(receiverText, 270, 30, 0);
ctx.textBaseline = 'bottom';
writeCaption(awardDateText, 490, 20, 300);
ctx.textBaseline = 'bottom';
writeCaption(signatureText, 490, 20, cvsWidth - 300 + ctx.measureText(signatureText).width);
}).trigger("keyup");
})
.attr("src", "<?php echo _SITE_URL; ?>images/editor/Template1.jpg")
.attr("id", "canvasimg");
var download = document.getElementById('canvas-download');
download.addEventListener('click', function () {
var canvas = document.getElementById('cs_canvas');
var data = canvas.toDataURL();
download.href = data;
}, false);
});
</script>
Here's the jsfiddle link for the working example.
http://jsfiddle.net/57gfqsm3/7/
Please help
I spent a long time trying to drag and drop images on a canvas tag this and eventually used kinetic.js.
https://github.com/ericdrowell/KineticJS/
I'll watch this post in case anyone has a better solution.
I found a sophisticated javascript canvas library called Fabric.
Click Here
Look: http://jsfiddle.net/MrHIDEn/QYL3t/
This code draws 3 boxes Reg,Green,Blue but context("2d") from Blue does do nothing. Why?
HTML:
<div id="divR">
<canvas id="cvsR" width="100" height="100" style="border:1px solid red"></canvas>
</div>
<div id="divG"></div>
<div id="divB"></div>
Javascript:
var cvsR = document.getElementById("cvsR");
var ctxR = cvsR.getContext("2d");
ctxR.fillStyle = "red";
ctxR.fillRect(0, 0, 50, 75);
var divG = document.getElementById("divG");
divG.innerHTML = '<canvas id="cvsG" width="100" height="100" style="border:1px solid green"></canvas>';
var cvsG = document.getElementById("cvsG");
var ctxG = cvsG.getContext("2d");
ctxG.fillStyle = "green";
ctxG.fillRect(0, 0, 50, 75);
// Dynamiclly
var divB = document.getElementById("divB");
var cvsB = document.createElement("canvas");
cvsB.width = 100;
cvsB.height = 100;
cvsB.style.border = "1px solid blue";
cvsB.id = "cvsB";
var ctxB = cvsB.getContext("2d");
ctxB.fillStyle = "blue";
ctxB.fillRect(0, 0, 50, 75);
divB.innerHTML = cvsB.outerHTML;
Your problem is here divB.innerHTML = cvsB.outerHTML;, with this code you aren't adding the canvas cvsB to divB but a can vas with the same html as cvsB. To add cvsB to the div just append it
divB.appendChild(cvsB);
http://jsfiddle.net/QYL3t/14/
I would append the canvas before reading the context, but it works without this, so this is just my personal preference:
cvsB.id = "cvsB";
divB.appendChild(cvsB);
var ctxB = cvsB.getContext("2d");
ctxB.fillStyle = "blue";
ctxB.fillRect(0, 0, 50, 75);