I am trying to make an interactive map for the website. There are areas under the house, and I want to mark them with different colors. I add canvas, path, and canvasBackground.
var canvas = new fabric.Canvas('c');
var path = new fabric.Path('M 756 349 L 744 308 L 787 310 L 794 346 z');
path.set({
fill: 'red',
opacity: 0.5
});
canvas.add(path);
canvas.setBackgroundImage('phase3.jpg', canvas.renderAll.bind(canvas), {
width: canvas.width,
height: canvas.height,
originX: 'left',
originY: 'top'
});
<canvas id="c" width="1600" height="900"></canvas>
Then i need to fit to screen. I try to use canvas.setDimensions(), but its not work.
Demo
Thx for help. Sorry for bad english)
How about put
canvas.setDimensions({
width: body_w,
height: body_h
});
to just behind var canvas = new fabric.Canvas('c');?
var width = 1600;
var height = 900;
var scaleFactor = 1;
if(screen.width < 1281) {
scaleFactor = 0.8;
} else if (screen.width < 1361) {
scaleFactor = 0.85;
} else if (screen.width < 1441) {
scaleFactor = 0.9;
} else if (screen.width < 1601) {
scaleFactor = 1;
} else {
scaleFactor = 1.2;
}
width = width * scaleFactor;
height = height * scaleFactor;
var canvas = new fabric.Canvas('canvas');
canvas.setWidth(width);
canvas.setHeight(height);
canvas.calcOffset();
if(scaleFactor != 1) {
for(var i=0; i<canvas._objects.length; i++){
canvas._objects[i].scale(scaleFactor);
canvas._objects[i].setLeft(canvas._objects[i].left * scaleFactor);
canvas._objects[i].setTop(canvas._objects[i].top * scaleFactor);
canvas._objects[i].setCoords();
}
canvas.renderAll();
} else {canvas.renderAll();}
I found this tip on stackoverflow, but lost link )
Related
I was trying to make a sphere using some data I found on Wikipedia about the Orthographic projection of a map and there's been something that has been keeping me busy for some time. When I run the project, on the center of the sphere there apears one pixel that is colored in a wrong way when changing the longitude. I tried to solve this problem in a lot of ways like using ifs to separe the wrong pixel from the rest of them or delaying the longitude of the wrong pixel but neither of those worked, can somebody help me?
var Canvas = document.getElementById("MainCanvas");
Canvas.style.imageRendering = "pixelated";
var Context = Canvas.getContext("2d");
var Sphere = {
radius: 80,
lat: 0,
long: 0
}
Render();
function Render()
{
let ImgData = Context.createImageData(Canvas.width, Canvas.height);
//Sphere.lat += 0.02;
Sphere.long += 0.01;
document.getElementById("Display").innerHTML = Sphere.long;
for(var y = 0; y != Canvas.height; y++)
{
for(var x = 0; x != Canvas.width; x++)
{
/*Get the true position*/
let TrueX = x - Canvas.width / 2;
let TrueY = Canvas.height / 2 - y;
/*Get the distance*/
let Dist = Math.sqrt(TrueX * TrueX + TrueY * TrueY);
if(Dist < Sphere.radius)
{
let C, CurrLat, CurrLong;
/*Get the depth of a sphere point*/
C = Math.asin(Dist / Sphere.radius);
/*Color the pixel*/
if(TrueX === 0 && TrueY === 0)
{
CurrLong = (Sphere.long) % (Math.PI);
CurrLat = (Sphere.lat) % (2*Math.PI);
}
else
{
/*Get the latitude (Clamped the value to 0 → π)*/
CurrLong = (Math.asin(Math.cos(C)*Math.sin(Sphere.long)+(TrueY*Math.sin(C)*Math.cos(Sphere.long))/Dist)) % Math.PI;
/*And the longitude (Clamped the value to 0 → 2π)*/
CurrLat = (Sphere.lat + Math.atan2((TrueX*Math.sin(C)), (Dist*Math.cos(C)*Math.cos(Sphere.long) - (TrueY*Math.sin(C)*Math.sin(Sphere.long))))) % (2*Math.PI);
}
ImgData.data[4*((y * Canvas.width)+x)] = (CurrLong / (Math.PI)) * 255;
ImgData.data[4*((y * Canvas.width)+x)+1] = 0;
ImgData.data[4*((y * Canvas.width)+x)+2] = (CurrLat / (Math.PI * 2)) * 255;
ImgData.data[4*((y * Canvas.width)+x)+3] = 255;
}
else
{
ImgData.data[4*((y * Canvas.width)+x)] = 200;
ImgData.data[4*((y * Canvas.width)+x)+1] = 200;
ImgData.data[4*((y * Canvas.width)+x)+2] = 200;
ImgData.data[4*((y * Canvas.width)+x)+3] = 255;
}
}
}
Context.putImageData(ImgData, 0, 0);
requestAnimationFrame(Render);
}
#MainCanvas
{
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-image: url("https://c.tenor.com/k9yAts9ymaIAAAAM/loading-load.gif");
background-size: 100vw 100vh;
}
#Display
{
position: absolute;
top: 10px;
left: 10px;
z-index: 10;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<canvas id="MainCanvas" width="400" height="200"></canvas>
<div id="Display"></div>
</body>
</html>
Ok, now I understand it. The value of longitude must be between -π/2 and π/2
I'm trying to add many flying dots to the canvas that connect to each other with a line when the distance between them is between 0 and 300 and have the line's opacity change based on the distance between them. As you can see, I've done all that completely with two dots. However, I'm facing two problems now.
Problem number one - If I wanted to add 15 ellipses, I'd more or less have to copy the code for each new ellipse. I'm fairly certain this is not the way to do it.
The second problem is that I'm hard-coding which dots should connect to each other. I want each dot to connect to each nearby dot, however, I'm not sure how to do that exactly.
var el1 = {
x: 100,
y: 100,
width: 5,
height: 5
};
var el2 = {
x: 300,
y: 300,
width: 5,
height: 5
};
var speed = 2;
var opacity = 0;
var xdirection = 1;
var ydirection = 1;
function setup() {
createCanvas(windowWidth, windowHeight - 4);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight - 4);
}
function draw() {
background(51, 51, 51);
fill(55, 90, 80);
noStroke();
ellipse(el1.x, el1.y, el1.width, el1.height);
ellipse(el2.x, el2.y, el2.width, el2.height);
el1.x = el1.x + speed * xdirection;
el1.y = el1.y + speed * ydirection;
if (el1.x > windowWidth || el1.x < 5) {
xdirection *= -1;
}
if (el1.y > windowHeight || el1.y < 5) {
ydirection *= -1;
}
if (dist(el1.x,el1.y,el2.x,el2.y) < 300) {
var opacity = map(dist(el1.x,el1.y,el2.x,el2.y),0, 300, 255, 0);
stroke(55, 90, 80, opacity);
line(el1.x,el1.y,el2.x,el2.y);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>
Define your ellipse as an object, create them as many as you want (15), put into array and start drawing, constantly detecting the distance between all of them.
Object himself:
var noOfEllipses = 15;
var opacity = 0;
var arrOfEllipses = [];
class Ellips {
constructor(x, y, w, h, s=2, dx=1, dy=1){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.s = s;
this.dx = dx;
this.dy = dy;
};
}
Next, initial drawing. I gave dots random dimensions and locations, you can add any individual property (speed/direction/color/etc).
function randInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
function setup() {
createCanvas(windowWidth, windowHeight - 4);
for(i=0; i<noOfEllipses;i++){
var el = new Ellips(
randInt(3, windowWidth), //x
randInt(3, windowHeight), //y
randInt(3, 8), //width
randInt(3, 8), //height
randInt(10, 50)/10 //speed
);
arrOfEllipses.push(el); //put them into array
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight - 4);
}
Animation. Iterate through array of dots, location/speed/etc. are inner properties. Second for{} is needed to calculate distance and draw lines.
function draw() {
background(51, 51, 51);
fill(200, 200, 80);
noStroke();
for(var i=0; i<arrOfEllipses.length; i++){
el = arrOfEllipses[i];
el.x = el.x + el.s * el.dx;
el.y = el.y + el.s * el.dy;
if (el.x > windowWidth || el.x < 5) {
el.dx *= -1;
}
if (el.y > windowHeight || el.y < 5) {
el.dy *= -1;
}
for(var j=i+1; j<arrOfEllipses.length; j++){
el2 = arrOfEllipses[j];
if (dist(el.x,el.y,el2.x,el2.y) < 300) {
var opacity = map(dist(el.x,el.y,el2.x,el2.y),0, 300, 255, 0);
stroke(200, 200, 80, opacity);
line(el.x,el.y,el2.x,el2.y);
}
}
ellipse(el.x, el.y, el.w, el.h);
}
}
I made a blurred banner which on mouse move became clear. For this I used 2 images, one blurred and one clear. I want to make the blur from css and use one single image but then when I put filter on this image the banner doesn't become clear on mouse move. Can anyone help me? Thanks! I tried many manners to put this filter but none works correctly.I need to use jpg or png not svg because theese are the formats that clients give me
var image = document.querySelector('.zzz img');
var imageCanvas = document.createElement('canvas');
var imageCanvasContext = imageCanvas.getContext('2d');
var lineCanvas = document.createElement('canvas');
var lineCanvasContext = lineCanvas.getContext('2d');
var pointLifetime = 9999999999999999999999999999;
var points = [];
if (image.complete) {
start();
} else {
image.onload = start;
}
/**
* Attaches event listeners and starts the effect.
*/
function start() {
document.addEventListener('mousemove', onMouseMove);
window.addEventListener('resize', resizeCanvases);
var xxx=document.querySelector('.banner');
xxx.appendChild(imageCanvas);
resizeCanvases();
tick();
}
/**
* Records the user's cursor position.
*
* #param {!MouseEvent} event
*/
function onMouseMove(event) {
var rect = document.querySelector('.banner').getBoundingClientRect();
points.push({
time: Date.now(),
x: event.clientX-rect.left,
y: event.clientY-rect.top
});
}
/**
* Resizes both canvases to fill the window.
*/
function resizeCanvases() {
imageCanvas.width = lineCanvas.width = 300;
imageCanvas.height = lineCanvas.height = 250;
}
/**
* The main loop, called at ~60hz.
*/
function tick() {
// Remove old points
points = points.filter(function(point) {
var age = Date.now() - point.time;
return age < pointLifetime;
});
drawLineCanvas();
drawImageCanvas();
requestAnimationFrame(tick);
}
/**
* Draws a line using the recorded cursor positions.
*
* This line is used to mask the original image.
*/
function drawLineCanvas() {
var minimumLineWidth = 25;
var maximumLineWidth = 100;
var lineWidthRange = maximumLineWidth - minimumLineWidth;
var maximumSpeed = 50;
lineCanvasContext.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
lineCanvasContext.lineCap = 'round';
lineCanvasContext.shadowBlur = 30;
lineCanvasContext.shadowColor = '#000';
for (var i = 1; i < points.length; i++) {
var point = points[i];
var previousPoint = points[i - 1];
// Change line width based on speed
var distance = getDistanceBetween(point, previousPoint);
var speed = Math.max(0, Math.min(maximumSpeed, distance));
var percentageLineWidth = (maximumSpeed - speed) / maximumSpeed;
lineCanvasContext.lineWidth = minimumLineWidth + percentageLineWidth * lineWidthRange;
// Fade points as they age
var age = Date.now() - point.time;
var opacity = (pointLifetime - age) / pointLifetime;
lineCanvasContext.strokeStyle = 'rgba(0, 0, 0, ' + opacity + ')';
lineCanvasContext.beginPath();
lineCanvasContext.moveTo(previousPoint.x, previousPoint.y);
lineCanvasContext.lineTo(point.x, point.y);
lineCanvasContext.stroke();
}
}
/**
* #param {{x: number, y: number}} a
* #param {{x: number, y: number}} b
* #return {number} The distance between points a and b
*/
function getDistanceBetween(a, b) {
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}
/**
* Draws the original image, masked by the line drawn in drawLineToCanvas.
*/
function drawImageCanvas() {
// Emulate background-size: cover
var width = 300;
var height = 250;
if (height < imageCanvas.height) {
width = imageCanvas.height / image.naturalHeight * image.naturalWidth;
height = imageCanvas.height;
}
imageCanvasContext.clearRect(0, 0, imageCanvas.width, imageCanvas.height);
imageCanvasContext.globalCompositeOperation = 'source-over';
imageCanvasContext.drawImage(image, 0, 0, width, height);
imageCanvasContext.globalCompositeOperation = 'destination-in';
imageCanvasContext.drawImage(lineCanvas, 0, 0);
}
.zzz img {
display: none;
}
.blur img{
filter:blur(5px);
}
.zzz{
position: absolute;
z-index:200;
}
.banner{
width: 300px;
height: 250px;
overflow: hidden;
position: relative;
margin:0 auto 0;
background-image: url('http://www.dbdesign.ro/blur/a_blur.png');
/* filter: blur(5px);
-webkit-filter: blur(5px);*/
/* background-image: filter(url(a.png), blur(20px));*/
/* filter: blur(5px);
-webkit-filter: blur(5px);*/
}
canvas{
position: absolute;
z-index:999;
}
<div class="banner" style="">
<div class="zzz"><img src="http://www.dbdesign.ro/blur/a.png"></div>
</div>
A simple way still using the canvas API, is to use a CanvasPattern from your original image, and only fill where your mouse passed.
Now, you can position your canvas over your CSS filtered <img> and it will cover it with the clear image:
img.onload = function() {
canvas.width = this.width;
canvas.height = this.height;
var rad = 30;
var ctx = canvas.getContext('2d');
ctx.fillStyle = ctx.createPattern(img, 'no-repeat');
canvas.onmousemove = handlemousemove;
function handlemousemove(evt) {
var x = evt.pageX - canvas.offsetLeft;
var y = evt.pageY - canvas.offsetTop;
draw(x, y);
}
function draw(x, y) {
ctx.beginPath();
ctx.moveTo(x + rad, y);
ctx.arc(x, y, rad, 0, Math.PI*2);
ctx.fill();
}
};
#banner{
position: relative;
}
#banner img{
filter: blur(5px);
}
#banner canvas{
position: absolute;
left: 0;
top: 0;
}
<div id="banner">
<img id="img" src="https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg">
<canvas id="canvas"></canvas>
</div>
I'm trying to resize a rotated shape on canvas. My problem is that when I call the rendering function, the shape starts "drifting" depending on the shape angle. How can I prevent this?
I've made a simplified fiddle demonstrating the problem, when the canvas is clicked, the shape is grown and for some reason it drifts upwards.
Here's the fiddle: https://jsfiddle.net/x5gxo1p7/
<style>
canvas {
position: absolute;
box-sizing: border-box;
border: 1px solid red;
}
</style>
<body>
<div>
<canvas id="canvas"></canvas>
</div>
</body>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
canvas.width = 300;
canvas.height= 150;
var ctx = canvas.getContext('2d');
var counter = 0;
var shape = {
top: 120,
left: 120,
width: 120,
height: 60,
rotation: Math.PI / 180 * 15
};
function draw() {
var h2 = shape.height / 2;
var w2 = shape.width / 2;
var x = w2;
var y = h2;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(75,37.5)
ctx.translate(x, y);
ctx.rotate(Math.PI / 180 * 15);
ctx.translate(-x, -y);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, shape.width, shape.height);
ctx.restore();
}
canvas.addEventListener('click', function() {
shape.width = shape.width + 15;
window.requestAnimationFrame(draw.bind(this));
});
window.requestAnimationFrame(draw.bind(this));
</script>
In the "real" code the shape is resized when the resize-handle is clicked and moved but I think this example demonstrates the problem sufficiently.
EDIT: updated fiddle to clarify the issue:
https://jsfiddle.net/x5gxo1p7/9/
Always use local coordinates to define shapes.
When rendering content that is intended to be transformed the content should be in its own (local) coordinate system. Think of a image. the top left pixel is always at 0,0 on the image no matter where you render it. The pixels are at their local coordinates, when rendered they are moved to the (world) canvas coordinates via the current transformation.
So if you make your shape with coordinates set to its local, making the rotation point at its local origin (0,0) the display coordinates are stored separately as world coordinates
var shape = {
top: -30, // local coordinates with rotation origin
left: -60, // at 0,0
width: 120,
height: 60,
world : {
x : canvas.width / 2,
y : canvas.height / 2,
rot : Math.PI / 12, // 15deg clockwise
}
};
Now you don't have to mess about with translating forward and back... blah blah total pain.
Just
ctx.save();
ctx.translate(shape.world.x,shape.world.y);
ctx.rotate(shape.world.rot);
ctx.fillRect(shape.left, shape.top, shape.width, shape.height)
ctx.restore();
or event quicker and eliminating the need to use save and restore
ctx.setTransform(1,0,0,1,shape.world.x,shape.world.y);
ctx.rotate(shape.world.rot);
ctx.fillRect(shape.left, shape.top, shape.width, shape.height);
The local shape origin (0,0) is where the transformation places the translation.
This greatly simplifies a lot of the work that has to be done
var canvas = document.getElementById('canvas');
canvas.width = 300;
canvas.height= 150;
var ctx = canvas.getContext('2d');
ctx.fillStyle = "black";
ctx.strokeStyle = "red";
ctx.lineWidth = 2;
var shape = {
top: -30, // local coordinates with rotation origin
left: -60, // at 0,0
width: 120,
height: 60,
world : {
x : canvas.width / 2,
y : canvas.height / 2,
rot : Math.PI / 12, // 15deg clockwise
}
};
function draw() {
ctx.setTransform(1,0,0,1,0,0); // to clear use default transform
ctx.clearRect(0, 0, canvas.width, canvas.height);
// you were scaling the shape, that can be done via a transform
// once you have moved the shape to the world coordinates.
ctx.setTransform(1,0,0,1,shape.world.x,shape.world.y);
ctx.rotate(shape.world.rot);
// after the transformations have moved the local to the world
// you can ignore the canvas coordinates and work within the objects
// local. In this case showing the unscaled box
ctx.strokeRect(shape.left, shape.top, shape.width, shape.height);
// and a line above the box
ctx.strokeRect(shape.left, shape.top - 5, shape.width, 1);
ctx.scale(0.5,0.5); // the scaling you were doing
ctx.fillRect(shape.left, shape.top, shape.width, shape.height);
}
canvas.addEventListener('click', function() {
shape.width += 15;
shape.left -= 15 / 2;
shape.world.rot += Math.PI / 45; // rotate to illustrate location
// of local origin
var distToMove = 15/2;
shape.world.x += Math.cos(shape.world.rot) * distToMove;
shape.world.y += Math.sin(shape.world.rot) * distToMove;
draw();
});
// no need to use requestAnimationFrame (RAF) if you are not animation
// but its not wrong. Nor do you need to bind this (in this case
// this = window) to the callback RAF does not bind a context
// to the callback
/*window.requestAnimationFrame(draw.bind(this));*/
requestAnimationFrame(draw); // functionaly identical
// or just
/*draw()*/ //will work
body { font-family : Arial,"Helvetica Neue",Helvetica,sans-serif; font-size : 12px; color : #242729;} /* SO font currently being used */
canvas { border: 1px solid red; }
<canvas id="canvas"></canvas>
<p>Click to grow "and rotate" (I add that to illustrate the local origin)</p>
<p>I have added a red box and a line above the box, showing how using the local coordinates to define a shape makes it a lot easier to then manipulate that shape when rendering "see code comments".</p>
Try this. You had ctx.translate() used where it was not entirely necessary. That caused the problems.
<script type="text/javascript">
var canvas = document.getElementById('canvas');
canvas.width = 300;
canvas.height= 150;
var ctx = canvas.getContext('2d');
var counter = 0;
var shape = {
top: 120,
left: 120,
width: 120,
height: 60,
rotation: Math.PI / 180 * 15
};
function draw() {
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(75,37.5)
ctx.rotate(Math.PI / 180 * 15);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, shape.width, shape.height);
ctx.restore();
}
canvas.addEventListener('click', function() {
shape.width = shape.width + 15;
window.requestAnimationFrame(draw.bind(this));
});
window.requestAnimationFrame(draw.bind(this));
</script>
This is happening because the x and y are set as the half value of the shape size, which completely changes its position.
You should set a point for the center of the shape, anyway. I set this point as ctx.canvas.[width or height] / 2, the half of the canvas.
var h2 = shape.height / 2;
var w2 = shape.width / 2;
var x = (ctx.canvas.width / 2) - w2;
var y = (ctx.canvas.height / 2) - h2;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(x + (shape.width / 2), y + (shape.height / 2));
ctx.rotate(((shape.rotation * Math.PI) / 180) * 15);
ctx.fillStyle = '#000';
ctx.fillRect(-shape.width / 2, -shape.height / 2, shape.width, shape.height);
ctx.restore();
Fiddle.
Found a solution, problem was that I wasn't calculating the new center point coordinates.
The new fiddle with solution: https://jsfiddle.net/HTxGb/151/
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width =500;
canvas.height = 500;
var x = canvas.width/2;
var y = canvas.height/2;
var rectw = 20;
var recth = 20;
var rectx = -rectw/2;
var recty = -recth/2;
var rotation = 0;
var addedRotation = Math.PI/12;
var addedWidth = 20;
var addedHeight = 10;
var draw = function() {
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(x, y);
ctx.rotate(rotation);
ctx.fillRect(rectx, recty, rectw, recth);
ctx.restore();
}
document.getElementById('growXRight').addEventListener('click', function() {
rectx -= addedWidth/2;
x += addedWidth/2 * Math.cos(rotation);
y -= addedWidth/2 * Math.sin(-rotation);
rectw += addedWidth;
draw();
})
document.getElementById('growXLeft').addEventListener('click', function() {
rectx -= addedWidth/2;
x -= addedWidth/2 * Math.cos(rotation);
y += addedWidth/2 * Math.sin(-rotation);
rectw += addedWidth;
draw();
})
document.getElementById('growYTop').addEventListener('click', function() {
recty -= addedHeight/2;
x += addedHeight/2 * Math.sin(rotation);
y -= addedHeight/2 * Math.cos(-rotation);
recth += addedHeight;
draw();
})
document.getElementById('growYBottom').addEventListener('click', function() {
recty -= addedHeight/2;
x -= addedHeight/2 * Math.sin(rotation);
y += addedHeight/2 * Math.cos(-rotation);
recth += addedHeight;
draw();
})
document.getElementById('rotatePlus').addEventListener('click', function() {
rotation += addedRotation;
rotation = rotation % (Math.PI*2);
if(rotation % Math.PI*2 < 0) {
rotation += Math.PI*2;
}
draw();
})
document.getElementById('rotateMinus').addEventListener('click', function() {
rotation -= addedRotation;
rotation = rotation % (Math.PI*2);
if(rotation % Math.PI*2 < 0) {
rotation += Math.PI*2;
}
draw();
})
draw();
I'm still very new to the canvas element and I'm trying to draw random polygon shapes (triangular shapes) in random places on the canvas element. But I have trouble getting my head around it.
I have this so far, which draws a ploygon nicely, but how to add the randomness and positioning completely eludes me
var c = document.getElementById('c');
if (c.getContext) {
c2 = c.getContext('2d');
var width = c2.width;
var height = c2.height;
var maxAmount = 20;
for (i = 0; i < maxAmount; i++) {
var polySize = 50;
var posx = (Math.random() * (width - polySize)).toFixed();
var posy = (Math.random() * (height - polySize)).toFixed();
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(posx, posy);
c2.lineTo(100, 50);
c2.lineTo(50, 100);
c2.lineTo(0, 90);
c2.closePath();
c2.fill();
}
}
<canvas id="c" \>
You are trying to get the width and height properties of the Context2D property of your canvas, which both returned undefined.
What you need instead is the canvas element's width and height properties.
Now, since your comment to the other answer, if you need to move the whole shape, just use the first point you saved in posx and posy variables and then adjust the other points positions :
var c = document.getElementById('c');
c.width =500;
c.height= 500;
if (c.getContext) {
var c2 = c.getContext('2d');
var width = c.width;
var height = c.height;
var maxAmount = 20;
for (var i = 0; i < maxAmount; i++) {
var polySize = 50;
var posx = (Math.random() * (width - polySize));
var posy = (Math.random() * (height - polySize));
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(posx, posy);
c2.lineTo(posx+100, posy+50);
c2.lineTo(posx+50,posy+100);
c2.lineTo(posx+0, posy+90);
c2.closePath();
c2.stroke();
c2.fill();
}
}
<canvas id="c"><\canvas>
Here canvas width and height properties are not set. so when invoke code following line of code, it returns NaN
var width = c2.width;
var height = c2.height;
To get random position try following code base
<canvas id="c" width="250" height="250" \>
var c = document.getElementById('c');
if (c.getContext)
{
c2 = c.getContext('2d');
var width = c.width;
var height = c.height;
var maxAmount = 5;
for (i = 0; i < maxAmount; i++) {
var polySize = 50;
var posx = (Math.random() * (width - polySize)).toFixed();
var posy = (Math.random() * (height - polySize)).toFixed();
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(posx, posy);
c2.lineTo(100, 50);
c2.lineTo(50, 100);
c2.lineTo(0, 90);
c2.closePath();
c2.fill();
}
}