>>> Jsfiddle
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(55,95,30,0,2*Math.PI);
ctx.stroke();
var canvas = document.getElementById('myCanvas'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src='https://www.gravatar.com/avatar/4af2cdbaf02d97ba88d5d6daff94fbae/?default=&s=80';
base_image.onload = function(){
context.drawImage(base_image, 20, 20);
}
}
<canvas id="myCanvas"
width="236"
height="413"
style="border:1px solid #000000;
position:absolute;
top:66px;
left:22px;"></canvas>
I have try to put the image in to canvas instead my circle position.
but i don't know how to resize square image to circle with same size of my draw circle and put in to the same position.
What should i do?
You have to use clip for this.
Here is Codepen for this http://codepen.io/sam83045/pen/eBKRPr?editors=0010
And your edited javascript code is as follows :
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(55, 95, 30, 0, 2 * Math.PI);
ctx.clip();
ctx.stroke();
var canvas = document.getElementById('myCanvas'),
context = canvas.getContext('2d');
make_base();
function make_base() {
base_image = new Image();
base_image.src = 'https://www.gravatar.com/avatar/4af2cdbaf02d97ba88d5d6daff94fbae/?default=&s=80';
base_image.onload = function() {
context.drawImage(base_image, 16, 55);
}
}
window.onload=function(){
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.addEventListener("click",function(){
ctx.clearRect(0, 0, c.width, c.height);
var object = images.shift();
images.push(object);
create(ctx);
},false)
var loaded=0;
var error=0;
var images=new Array
(
{
image:null,
url:"https://www.gravatar.com/avatar/4af2cdbaf02d97ba88d5d6daff94fbae/?s=80",
expandW:0,
expandH:0,
clip:false,
visible:true,
shape:
{
x:0,
y:0,
rect:
{
w:30,
h:50
},
boundary:
function(){return {w:this.rect.w,h:this.rect.h,centerX:this.rect.w/2,centerY:this.rect.h/2};}
}
},
{
image:null,
url:"http://iconbug.com/data/7c/512/6e1cd685219a18b951b191ad04407324.png",
expandW:0,
expandH:0,
clip:true,
visible:true,
shape:
{
x:30,
y:30,
circle:
{
r:30
},
boundary:
function(){return {w:this.circle.r*2,h:this.circle.r*2,centerX:0,centerY:0};}
}
}
);
function loadImages(ctx)
{
for (var i=0;i<images.length;i++)
{
images[i].image= new Image();
images[i].image.src = images[i].url;
images[i].image.onerror=function(){
loaded++;
error++;
loadedText(images.length,loaded,error);
if(loaded===images.length)
{
create(ctx);
}
};
images[i].image.onload=function(){
loaded++;
loadedText(images.length,loaded,error);
if(loaded===images.length)
{
create(ctx);
}
};
}
}
function loadedText(sum,count,error)
{
if(error)
console.log((count-error)+" images loaded from "+count+"."+error+" images not loaded.");
else
console.log(count+" images loaded from "+count+".");
}
function create(ctx)
{
for (var i=0;i<images.length;i++)
{
ctx.save();
if(images[i].image !==null && images[i].visible)
{
var object=images[i];
var boundary=object.shape.boundary();
var image=object.image;
var shape=object.shape;
if(shape.circle)
{
drawCircle(
shape.x,
shape.y,
shape.circle.r,
ctx,
object.clip
);
}
if(shape.rect)
{
drawRect(
shape.x,
shape.y,
shape.rect.w,
shape.rect.h,
ctx,
object.clip
);
}
if(!object.clip)
{
image.width=image.width*(boundary.w/image.width);
image.height=image.height*(boundary.h/image.height);
}
image.width=image.width+object.expandW;
image.height=image.height+object.expandH;
var x=(shape.x+boundary.centerX)-image.width/2;
var y=(shape.y+boundary.centerY)-image.height/2;
ctx.drawImage(image, x, y,image.width,image.height);
}
ctx.restore();
}
}
function drawCircle(x,y,r,ctx,clip){
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
if(clip)
{
ctx.clip();
}
ctx.stroke();
}
function drawRect(x,y,w,h,ctx,clip){
ctx.beginPath();
ctx.rect(x, y, w, h);
if(clip)
{
ctx.clip();
}
ctx.stroke();
}
loadImages(ctx);
};
Add multiple images.
If you do not have many pictures, it is easier to load them at once.
On console (F12) you can see load progress.
Every image has is own options.
image- it will populated latter
url- address
expandW, expandH- you can manipulate Picture after clipping.
clip- do we make picture size of image or we clip shape from image.
visible- do we show image.
shape-clipping shape
shape options
x,y-position of shape
rect or circle type of shape.
boundary- we get shape centre position and shape with and height. (circle with and height is actually double of radius).
with mouse click on canvas you can cycle through all loaded pictures.
Related
(function() {
// Creates a new canvas element and appends it as a child
// to the parent element, and returns the reference to
// the newly created canvas element
function createCanvas(parent, width, height) {
var canvas = {};
canvas.node = document.createElement('canvas');
canvas.context = canvas.node.getContext('2d');
canvas.node.width = width || 100;
canvas.node.height = height || 100;
parent.appendChild(canvas.node);
return canvas;
}
function init(container, width, height, fillColor) {
var canvas = createCanvas(container, width, height);
var ctx = canvas.context;
// define a custom fillCircle method
ctx.fillCircle = function(x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
ctx.clearTo = function(fillColor) {
ctx.fillStyle = fillColor;
ctx.fillRect(0, 0, width, height);
};
ctx.clearTo(fillColor || "yel");
// bind mouse events
canvas.node.onmousemove = function(e) {
if (!canvas.isDrawing) {
return;
}
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var radius = 40; // or whatever
var fillColor = '#ff0000';
ctx.globalCompositeOperation = 'destination-out';
ctx.fillCircle(x, y, radius, fillColor);
};
canvas.node.onmousedown = function(e) {
canvas.isDrawing = false;
};
canvas.node.onmouseup = function(e) {
canvas.isDrawing = true;
};
}
var img = document.createElement("img");
img.src= "blm.jpg";
var container = document.getElementById('canvas');
init(container, window.innerWidth, window.innerHeight, 'img');
})();
Hi im trying to make a cover for my canvas instead of just a plain black color on my code. instead i would like my image named "blm.jpg" to replace the plain black. Im not sure how to. Im very new to coding and would really appreciate any help that i can get :) I added the var img = document 5 lines from the bottom and the 4th line from the bottom, im not sure if thats meant to be there either.
thank you for any help in advance :)
Here is a simple example on how to do that, I'm just drawing grids over the background image
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
backgroundImage = document.createElement("img");
backgroundImage.src = "https://openclipart.org/image/400px/svg_to_png/260587/Surreal-Fantastic-Nature.png";
function makeLine(start_x, start_y, end_x, end_y) {
ctx.moveTo(start_x, start_y);
ctx.lineTo(end_x, end_y);
}
function drawGrid(val, color) {
ctx.beginPath();
ctx.strokeStyle = color;
for(var i = 0; i <= canvas.height; i += val) {
makeLine(0, i, canvas.width, i);
}
for(var j = 0; j <= canvas.width; j += val) {
makeLine(j, 0, j, canvas.height);
}
ctx.stroke();
}
// draw it first to make it the background and only when it loads
backgroundImage.onload = function() {
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
drawGrid(10, "blue");
drawGrid(20, "red");
drawGrid(40, "black");
}
canvas {
border-radius: 3px;
box-shadow: 1px 1px 10px blue;
}
<canvas width="320" height="200">
You may noticed that we need to wait for the image to load for drawing it and draw other stuff, but here is another way by wrapping the whole code into the window.onload method and add our image as an HTML element and hide it of course
window.onload = function() {
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
backgroundImage = document.querySelector("#background-img");
function makeLine(start_x, start_y, end_x, end_y) {
ctx.moveTo(start_x, start_y);
ctx.lineTo(end_x, end_y);
}
function drawGrid(val, color) {
ctx.beginPath();
ctx.strokeStyle = color;
for(var i = 0; i <= canvas.height; i += val) {
makeLine(0, i, canvas.width, i);
}
for(var j = 0; j <= canvas.width; j += val) {
makeLine(j, 0, j, canvas.height);
}
ctx.stroke();
}
// no need for the .onload since the code is executing after everything loads
ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
drawGrid(10, "blue");
drawGrid(20, "red");
drawGrid(40, "black");
}
canvas {
border-radius: 3px;
box-shadow: 1px 1px 10px blue;
}
.hidden {
display: none;
}
<canvas width="320" height="200"></canvas>
<img id="background-img" class="hidden" src="https://openclipart.org/image/400px/svg_to_png/260587/Surreal-Fantastic-Nature.png" alt="nature painting">
This is the code that creates the arrow:
I need to detect the orientation where the arrow is pointing both when starting or doing some transformation of the arrow
var Arrow = Fabric.util.createClass(Fabric.Line, Fabric.Observable, {
type: 'arrow',
positionArrow: 'rt',
initialize: function (points, options) {
this.callSuper('initialize', points, options);
this.on('modified', function() {
console.log(this.toObject())
});
},
_render: function(ctx, noTransform) {
this._setStrokeStyles(ctx);
this._drawArrowHead(ctx);
this.callSuper('_render', ctx, noTransform);
},
_drawArrowHead: function(ctx) {
var p = this.calcLinePoints();
var rot = Math.atan2(p.y2, p.x2);
ctx.save();
ctx.beginPath();
ctx.translate(p.x1, p.y1);
ctx.moveTo(0, 0);
ctx.rotate(rot);
ctx.lineTo(15, 7);
ctx.lineTo(3, 0);
ctx.lineTo(15, -7);
ctx.lineTo(0, 0);
ctx.stroke();
ctx.closePath();
ctx.restore();
},
_setStrokeStyles: function(ctx) {
if (this.stroke) {
ctx.lineWidth = this.strokeWidth;
ctx.lineCap = this.strokeLineCap;
ctx.lineJoin = this.strokeLineJoin;
ctx.miterLimit = this.strokeMiterLimit;
ctx.strokeStyle = this.stroke.toLive ? this.stroke.toLive(ctx) : this.stroke;
}
}
});
I have added an observer when the object is transformed in the initialization, but I have found the way to know in which position the arrow is pointing.
If you know how much you should rotate the canvas to draw an arrowHead, you should also be able to get the full angle reusing that code and adding the object angle.
fabric.Arrow = fabric.util.createClass(fabric.Line, {
type: 'arrow',
positionArrow: 'rt',
initialize: function (points, options) {
this.callSuper('initialize', points, options);
this.on('modified', function() {
var p = this.calcLinePoints();
var rot = Math.atan2(p.y2, p.x2);
var rotDeg = fabric.util.radiansToDegrees(rot);
console.log(this.angle + rotDeg)
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
this._setStrokeStyles(ctx);
this._drawArrowHead(ctx);
},
_drawArrowHead: function(ctx) {
var p = this.calcLinePoints();
var rot = Math.atan2(p.y2, p.x2);
ctx.save();
ctx.beginPath();
ctx.translate(p.x1, p.y1);
ctx.moveTo(0, 0);
ctx.rotate(rot);
ctx.lineTo(15, 7);
ctx.lineTo(3, 0);
ctx.lineTo(15, -7);
ctx.lineTo(0, 0);
ctx.stroke();
ctx.closePath();
ctx.restore();
},
_setStrokeStyles: function(ctx) {
if (this.stroke) {
ctx.lineWidth = this.strokeWidth;
ctx.lineCap = this.strokeLineCap;
ctx.lineJoin = this.strokeLineJoin;
ctx.miterLimit = this.strokeMiterLimit;
ctx.strokeStyle = this.stroke.toLive ? this.stroke.toLive(ctx) : this.stroke;
}
}
});
var canvas = new fabric.Canvas('c');
var arrow = new fabric.Arrow([10,10, 70,20]);
canvas.add(arrow);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.js"></script>
<canvas id="c" width="300" height="300" ></canvas>
I have a problem with canvas. Let's say, 1/10 time I have black square instead of my image, on chrome. My code is as follow, how can I modify it in order to avoid this black display?
<canvas id="Canvas" width="954" height="267"></canvas>
<script>
var canvas = document.getElementById('Canvas');
var context = canvas.getContext("2d");
// Map sprite
var mapSprite = new Image();
mapSprite.src = 'image.png';
var main = function () {
draw();
};
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw diagramme
context.drawImage(mapSprite, 0, 0, 954, 267);
}
main();
</script>
EDIT 1: full function draw :
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw diagramme
context.drawImage(mapSprite, 0, 0, nextWidth, nextHeight);
//draw all precedent cross
cross = new Image();
cross.src = "cross.png";
for (var i = 0; i < array_x.length; i++) {
context.drawImage(cross, array_x[i], array_y[i], 10, 10);
}
}
I believe you want to wait until image is loaded.
Replace:
main();
With:
mapSprite.addEventListener('load', main);
I need help trying to rotate the rectangle that I have drawn on the canvas. I would like the top of the rectangle to pivot either to the right or left once I press on the arrow keys on my keyboard. This is my code so far:
HTML:
<body >
<div id="canvas-container">
<canvas id="canvas" width="500" height="400"></canvas>
</div>
</body>
CSS:
canvas {
display: inline;
}
Javascript:
document.addEventListener("DOMContentLoaded", function() {
drawBorder();
});
var canvas;
var context;
var size;
drawRectangle();
drawHalfCircle();
function drawBorder() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
size = {
x: canvas.width,
y: canvas.height
};
//have to set colors etc befor it is drawn
context.strokeStyle = 'black';
//takes 4 parameters
context.strokeRect(0, 0, size.x, size.y);
}
function drawRectangle() {
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.rect(246, 290, 8, 80);
ctx.stroke();
}
function drawHalfCircle(){
var c= document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.arc(250,579,308,1.2*Math.PI, 1.8*Math.PI);
ctx.stroke();
}
I have mocked something up is this along the correct lines of what you are wanting.
document.addEventListener("DOMContentLoaded", function() {
drawBorder();
});
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var size;
var angle = 0;
setInterval(function () {
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
drawBorder();
drawHalfCircle();
drawRectangle();
context.restore();
}, 100);
function drawBorder() {
size = {
x: canvas.width,
y: canvas.height
};
//have to set colors etc befor it is drawn
context.strokeStyle = 'black';
//takes 4 parameters
context.strokeRect(0, 0, size.x, size.y);
}
function drawRectangle() {
context.rotate(Math.PI / 180 * (angle));
context.rect(246, 290, 8, 80);
context.stroke();
}
function drawHalfCircle(){
context.beginPath();
context.arc(250,579,308,1.2*Math.PI, 1.8*Math.PI);
context.stroke();
}
document.onkeydown = function(e) {
var event = window.event ? window.event : e;
if (e.keyCode == '37') {
angle += 5;
}
else if (e.keyCode == '39') {
angle -= 5;
}
}
Basically set an interval and redraw (ie frames like in a movie) and rotate via a variable.
See a demo here
https://jsbin.com/qititacazu/edit?js,output
If you want to translate it so it will rotate around a different point do something like this.
context.translate(246, 290);
context.rotate(Math.PI / 180 * (angle));
context.rect(-4, 0, 4, 80);
I wrote some code that draws a semi-transparent rectangle over an image that you can draw with touch:
function drawRect() {
var canvas = document.getElementById('receipt');
var ctx = canvas.getContext('2d');
var drag = false;
var imageObj;
var rect = { };
var touch;
canvas.width = WIDTH;
canvas.height = HEIGHT;
function init() {
imageObj = new Image();
imageObj.src = 'img.jpg';
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0);
};
canvas.addEventListener('touchstart', handleTouch, false);
canvas.addEventListener('touchmove', handleTouch, false);
canvas.addEventListener('touchleave', handleEnd, false);
canvas.addEventListener('touchend', handleEnd, false);
}
function handleTouch(event) {
if (event.targetTouches.length === 1) {
touch = event.targetTouches[0];
if (event.type == 'touchmove') {
if (drag) {
rect.w = touch.pageX - rect.startX;
rect.h = touch.pageY - rect.startY ;
draw();
}
} else {
rect.startX = touch.pageX;
rect.startY = touch.pageY;
drag = true;
}
}
}
function handleEnd(event) {
drag = false;
}
function draw() {
drawImageOnCanvas();
ctx.fillStyle = 'rgba(0, 100, 255, 0.2)';
ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
}
function drawImageOnCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(imageObj, 0, 0);
}
init();
}
This works. But, now I'd like to have it so that I can capture each of the parts of the image that are in rectangles as separate images.
How can I pull this off? Because I have that redraw stuff, it deletes the previous rectangle, which makes this difficult.
A canvas can only save out the whole canvas as an image, so the trick is to create a temporary canvas the size of the region you want to save out.
One way could be to create a function which takes the image and a rectangle object as argument and returns a data-uri (or Blob) of the region:
function saveRegion(img, rect) {
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");
canvas.width = rect.w;
canvas.height = rect.h;
ctx.drawImage(img, rect.startX, rect.startY, rect.w, rect.h, 0, 0, rect.w, rect.h);
return canvas.toDataURL():
}
You can pass in the original image if don't want any graphics on top, or if you draw elements on top of it just pass in the original canvas element as image source. And of course, CORS-restrictions apply.