Can only see first of two canvases (drawing using ionic framework) - javascript

I have a problem displaying two canvases on top of each other.
I'm using the ionic framework and easeljs to draw on one canvas. Now I want to also be able to see a cursor of varying size and color when using a mouse (not in-app of course), so I though I could draw on the lower layer canvas and show the cursor on a higher layer canvas, clearing it repeatedly on mouse move.
I have an ionic on-drag event, an on-touch event (both to draw) and an angujarjs ng-mousemove (for the cursor). I have to put all those events in the first canvas in the html file or they won't register.
The problem is that I can only see the content of that first layer. I though canvases were transparent objects so I could layer them on top of each other using a different z-index for each one.
The following is my code using ionic and easeljs, I tried to keep it as short as possible. If you run it this way you can only draw, but you don't see a cursor. If you switch out the ids layer0 and layer1 it is the other way around.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Doodle</title>
<script src="ionic.bundle.js"></script>
<script src="easeljs-0.8.1.combined.js"></script>
<script type="text/javascript">
angular.module('starter', ['ionic'])
.controller('DrawCtrl', function($scope) {
var canvas, stage;
var drawingCanvas;
var oldPt;
var oldMidPt;
canvas = document.getElementById("layer0");
//check to see if we are running in a browser with touch support
stage = new createjs.Stage(canvas);
stage.autoClear = false;
stage.enableDOMEvents(true);
createjs.Touch.enable(stage);
createjs.Ticker.setFPS(24);
drawingCanvas = new createjs.Shape();
stage.addChild(drawingCanvas);
$scope.downEvent = function() {
oldPt = new createjs.Point(stage.mouseX, stage.mouseY);
oldMidPt = oldPt.clone();
};
$scope.dragEvent = function() {
//draw on layer0, don't clear
oldPt.x = stage.mouseX;
oldPt.y = stage.mouseY;
var midPt = new createjs.Point(oldPt.x + stage.mouseX >> 1, oldPt.y + stage.mouseY >> 1);
drawingCanvas.graphics.clear().setStrokeStyle(10, 'round', 'round').beginStroke("#000000").moveTo(midPt.x, midPt.y).curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);
oldMidPt.x = midPt.x;
oldMidPt.y = midPt.y;
stage.update();
};
$scope.mouseMove = function() {
//draw circle on canvas during mouse move, immediately clear layer1 again (like a cursor)
var ctx = document.getElementById('layer1').getContext('2d');
ctx.globalCompositeOperation = "source-over";
ctx.clearRect(0, 0, canvas.width, canvas.height);
var x = stage.mouseX;
var y = stage.mouseY;
ctx.fillStyle = "#000000";
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
};
})
</script>
</head>
<body ng-app="starter" ng-controller="DrawCtrl">
<canvas id="layer0" style="z-index:0; border: 1px solid black; " width="300" height="180" ng-mousemove="mouseMove()" on-touch="downEvent($event)" on-drag="dragEvent()" <="" canvas="">
<canvas id="layer1" style="z-index:1; border: 1px solid black; " width="300" height="180" <="" canvas="">
</canvas></canvas></body>
</html>
I'm just starting to learn html/javascript and would really appreciate any input!

A quick guess, but your problem is probably in your canvas HTML lines:
<canvas id="layer0" style="z-index:0; border: 1px solid black; " width="300" height="180" ng-mousemove="mouseMove()" on-touch="downEvent($event)" on-drag="dragEvent()" <="" canvas="">
<canvas id="layer1" style="z-index:1; border: 1px solid black; " width="300" height="180" <="" canvas="">
This bit at the end: <="" canvas=""> isn't quite valid. Replace those lines with:
<canvas id="layer0" style="z-index:0; border: 1px solid black; " width="300" height="180" ng-mousemove="mouseMove()" on-touch="downEvent($event)" on-drag="dragEvent()"></canvas>
<canvas id="layer1" style="z-index:1; border: 1px solid black; " width="300" height="180"></canvas>
And remove the 2 trailing </canvas></canvas>.

Related

How can I load a canvas inside a div with Vue?

I am really new to Vue and for this project, I was trying to load canvas inside a div. If the canvas is loaded outside of a div it works correctly but I want to display a canvas if loadModal is true only. In this code I have used two canvas one is inside div and other one is outside of div. It loads canvas correctly outside of div only. Is there a way to load canvas inside div as well? Here is my code below on JsFiddle
JsFiddle Code = https://jsfiddle.net/ujjumaki/6vg7r9oy/9/
View
<div id="app">
<button #click="runModal()">
Click Me
</button>
<br><br>
<div v-if="loadModal == true">
<canvas id="myCanvas" width="200" height="100" style="border:3px solid #d3d3d3; color:red;">
</canvas>
</div>
<!-- this one loads correctly -->
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">
</canvas>
</div>
Method
new Vue({
el: "#app",
data: {
loadModal: false,
},
methods: {
runModal(){
this.loadModal = true;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
}
}
})
Try with v-show and with class instead id, so you can select all divs:
new Vue({
el: "#app",
data: {
loadModal: false,
},
methods: {
runModal(){
this.loadModal = true;
const c = document.querySelectorAll("canvas");
c.forEach(can => {
let ctx = can.getContext("2d");
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
})
}
}
})
Vue.config.productionTip = false
Vue.config.devtools = false
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
del {
color: rgba(0, 0, 0, 0.3);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="runModal()">
Click Me
</button>
<br><br>
<div v-show="loadModal == true">
<canvas class="canvas" id="myCanvas" width="200" height="100" style="border:3px solid #d3d3d3; color:red;">
</canvas>
</div>
<canvas class="canvas" id="myCanvas" width="200" height="100" style="border:3px solid #d3d3d3; color:red;">
</canvas>
</div>
The problem is runModal() sets loadModal to true and immediately tries to reference the <canvas> inside the conditionally rendered <div v-if="loadModal">, but the <div> (and its <canvas>) is still not rendered yet. The effect of the loadModal change is not complete until the next render cycle. The <canvas> outside the <div> "loads" correctly because it's not conditionally rendered.
One solution is to await the next render cycle with the $nextTick() callback before trying to access the <canvas>:
new Vue({
methods: {
async runModal() {
this.loadModal = true;
// await next render cycle
await this.$nextTick();
// <canvas id="myCanvas"> is available here
var c = document.getElementById("myCanvas");
⋮
}
}
})
updated fiddle
Alternatively, using <div v-show="loadModal"> (as described in another answer) also works because the <canvas> is already rendered in the document and thus available to query. If you rather prefer to lazily render the <canvas>, stick with v-if="loadModal".

Dynamically load images into overlayed canvases and resize them

I have two canvases, which are overlaid. Now I want to load dynamically images into the canvases and adapt their size to the image size.
My problem now, is that after the canvases load the images and resize them self, they overlay all other html items below.
Here is the minimal example:
loadimage.onclick = function(e) {
//load image1
var img1 = new Image();
img1.onload = function() {
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
};
img1.src = "https://via.placeholder.com/250/0000FF/808080/";
//load image2
var img2 = new Image();
img2.onload = function() {
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 75, 75);
};
img2.src = "https://via.placeholder.com/50/00FF00/808080/";
}
<div id="container" style="position: relative; width: 200px; height: 100px;">
<canvas id="canvas1" width="200" height="100" style="position: absolute; left: 0; top: 0; z-index: 0; border: 1px solid #000;"></canvas>
<canvas id="canvas2" width="200" height="100" style="position: absolute; left: 0; top: 0; z-index: 1; border: 1px solid #000;"></canvas>
</div>
<button id="loadimage" type="button">Load Content</button>
After pressing the "Load Content"
button, the button doesn 't move down.
I tried to change also the width and height properties of the "container"
div, but the behaviour did not change.
What am I missing here ?
So, the code has many problems. If you are beginner, don't worry. That's normal. ☺
Firstly, <canvas> is pair tag. That means that you have to close it using </canvas>. The correct form is <canvas someattribute="somevalue"></canvas>. Inside the <canvas> tag is place for alternative content that will be used when the browser does not support the <canvas> tag (it is quite new).
Omitting the </canvas> broke the page.
HTML dictates what tags must be closed and what shouldn't and <canvas> is one of tags that must be closed. The Validator could help you identify mistakes in the code. Note that it is quite pedantic.
The second problem is that you were using absolute positioning and the canvases, when resized, overlaid the button. Simply disable the positioning or use some more precise way of positioning. The third option is to resize the container div appropriately in the JS.
The container div had also set fixed size. By default, when the content is larger, it overflows.
You were probably trying to solve it using z-index. Setting z-indexes is usually quite tricky and I try to use it as the last resort. Both your z-index properties were not valid. It is z-index: NUMBER, not z- index or z index.
And the last bug I have found was that you were using canvas1 (undefined variable) instead of canvas in the second function.
loadimage.onclick = function(e) {
//load image1
var img1 = new Image();
img1.onload = function() {
var canvas = document.getElementById("canvas1");
var ctx = canvas1.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
};
img1.src = "https://via.placeholder.com/250/0000FF/808080/";
//load image2
var img2 = new Image();
img2.onload = function() {
var canvas = document.getElementById("canvas2");
var ctx = canvas.getContext("2d");
//resize canvas1
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
ctx.drawImage(this, 0, 0);
};
img2.src = "https://via.placeholder.com/50/00FF00/808080/";
}
<div id="container">
<canvas id="canvas1" width="200" height="100" style="border: 1px solid #000;"></canvas>
<canvas id="canvas2" width="200" height="100" style="border: 1px solid #000;"></canvas>
</div>
<button id="loadimage" type="button">Load Content</button>

Fabric.js beta2 – text underline options

How can we exactly get and set the underline, overline etc. properties now for text, iText and Textbox in the 2.x beta? Is there some documentation available?
var canvas = new fabric.Canvas('canvas');
var text = new fabric.Text('FabricJS is Awsome.',{
fontSize:'30',
left:50,
top:50,
underline:true
});
canvas.add(text);
//text.setSelectionStyles({overline:true},0,5);
canvas.renderAll();
function changeStyle(val){
text[val] = !text[val];
text.dirty = true;
canvas.renderAll();
}
canvas {
border: 2px dotted green;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<button onclick=changeStyle('underline')>underline</button>
<button onclick=changeStyle('overline')>overline</button>
<button onclick=changeStyle('linethrough')>linethrough</button><br>
<canvas id="canvas" width="400" height="400"></canvas>
Same as other property set/get from object. fabric.Text

Why fill() property overwittern in canvas?

I am learner html5 canvas
When I try to draw 2 circle (a circle within a circle).
When I draw a circle and fill it, it works.
when I draw second circle and fill it. it turns into first circle with second fill style.
What I try to create is a orange circle in a grey circle.
I tries many time to solve this but by each way it get problem..
Please check my code and let me know if i am wrong or what to do to fix this problem.
I have following code
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"> </script>
<style>
body{
}
#mycanvas{
border:1px solid #000;
margin:0px auto;
display:block;
}
#mycanvas1{
border:1px solid #000;
margin:0px auto;
display:block;
}
</style>
<body>
<canvas id="mycanvas" width="200" height="200">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas id="mycanvas1" width="200" height="200">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript">
var c = document.getElementById("mycanvas");
var b = document.getElementById("mycanvas1");
var d = document.getElementById("mycanvas1");
var ctx = c.getContext("2d");
var ctx1 = b.getContext("2d");
var ctx2 = d.getContext("2d");
ctx.fillStyle = "#bddfb3";
ctx.fillRect(0,0,200,200);
ctx.moveTo(0,0);
ctx.lineTo(200,200);
ctx.stroke();
ctx1.fillStyle = "#f1b147";
ctx1.arc(100,100,80,0,360);
ctx1.fill();
ctx2.fillStyle = "#222";
ctx2.arc(100,100,50,45,180);
ctx2.fill();
ctx1.fillStyle="#fff";
ctx1.font="72px Arial";
ctx1.fillText("i",90,125);
</script>
</body>
</html>
This is a easy way to draw a orange circle inside a grey circle on canvas.
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
// orange circle
ctx.beginPath();
// centerX, centerY, radius, start angle, end angle, counterclockwise
ctx.arc(100, 100, 50, 0, 2 * Math.PI, false);
ctx.fillStyle = 'orange';
ctx.fill();
// grey circle
ctx.lineWidth = 25;
ctx.strokeStyle = 'grey';
ctx.stroke();
<canvas id="canvas" width="500" height="250"></canvas>

Drawing circles to canvas using functions

<div>
<canvas id="canvas" width="250px" height="400px" style="border: 1px solid black" onload="drawCircle()"></canvas>
</div>
<script type="text/javascript" src="canvasjs.js"></script>
</body>
</html>
var canv = document.getElementById("canvas");
var ctx = canv.getContext("2d");
function drawCircle(){
ctx.fillStyle="blue";
ctx.beginPath();
ctx.arc(50,50,50,0,Math.PI*2);
ctx.closePath();
ctx.fill();
}
Just wondering if anyone can tell me why this does not draw to canvas. If I remove the code from the function it works.
You did not invoke your function.
please append this code below your codes;
drawCircle();

Categories