EDIT::
I have converted the various points to (x,y) just as I wanted. I changed the name from bolt to drop because I already have an established shape named drop. However, it will not draw on the canvas. I replaced the coordinates with a leaf shape I also drew and converted to (x,y) and it worked fine. I can't figure out what's so different about my bolt shape.
context.beginPath();
context.moveTo(drop.x,drop.y);
context.moveTo(drop.x+140,drop.y+28);
context.lineTo(drop.x+24,drop.y+28);
context.moveTo(drop.x+24,drop.y+28);
context.lineTo(drop.x-2,drop.y+25);
context.moveTo(drop.x-2,drop.y+25);
context.lineTo(drop.x+17,drop.y+25);
context.moveTo(drop.x+17,drop.y+25);
context.lineTo(drop.x-18,drop.y+53);
context.moveTo(drop.x-18,drop.y+53);
context.lineTo(drop.x-3,drop.y+54);
context.moveTo(drop.x-3,drop.y+54);
context.lineTo(drop.x-47,drop.y+77);
context.moveTo(drop.x-47,drop.y+77);
context.lineTo(drop.x-31,drop.y+59);
context.moveTo(drop.x-31,drop.y+59);
context.lineTo(drop.x-40,drop.y+59);
context.moveTo(drop.x-40,drop.y+59);
context.lineTo(drop.x-14,drop.y+33);
context.moveTo(drop.x-14,drop.y+33);
context.lineTo(drop.x-30,drop.y+32);
context.moveTo(drop.x-30,drop.y+32);
context.lineTo(drop.x+140,drop.y+28);
context.closePath();
context.fillStyle = 'yellow';
context.fill();
I'm not sure what I want to do is called. This is the code my professor provided for a cloud.
function drawCloud(cloud) {
context.beginPath();
context.moveTo(cloud.x, cloud.y);
context.bezierCurveTo(cloud.x-40, cloud.y+20, cloud.x-40, cloud.y+70, cloud.x+60, cloud.y+70);
context.bezierCurveTo(cloud.x+80, cloud.y+100, cloud.x+170, cloud.y+100, cloud.x+170, cloud.y+70);
context.bezierCurveTo(cloud.x+250, cloud.y+70, cloud.x+250, cloud.y+40, cloud.x+210, cloud.y+20);
context.bezierCurveTo(cloud.x+260, cloud.y-40, cloud.x+200, cloud.y+50, cloud.x+170, cloud.y-30);
context.bezierCurveTo(cloud.x+150, cloud.y-75, cloud.x+80, cloud.y-60, cloud.x+80, cloud.y-30);
context.bezierCurveTo(cloud.x+30, cloud.y-75, cloud.x-20, cloud.y-60, cloud.x, cloud.y);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.strokeStyle = cloud.color;
context.stroke();
}
I found the shape generator and made this shape
function drawBolt(bolt){
context.beginPath()
context.moveTo(140,28);
context.lineTo(164,28);
context.moveTo(164,28);
context.lineTo(138,53);
context.moveTo(138,53);
context.lineTo(157,53);
context.moveTo(157,53);
context.lineTo(122,81);
context.moveTo(122,81);
context.lineTo(137,82);
context.moveTo(137,82);
context.lineTo(93,105);
context.moveTo(93,105);
context.lineTo(109,87);
context.moveTo(109,87);
context.lineTo(100,87);
context.moveTo(100,87);
context.moveTo(126,61);
context.lineTo(110,60);
context.moveTo(110,60);
context.lineTo(140,28);
context.closePath();
context.fill();
};
She told me that I had to change those points to x,y and I imagine there is math involved? Is there an easy way of doing that?
So how she has (cloud.x-40) I suppose I need bolt.x(?)
Where is a good starting point?
var canvas;
var context;
var shapes = []
var timer;
var timerTwo;
var possibleShapes = ['drop','triangle','square','circle','cloud'];
function Shape(x, y, color) {
this.x = x;
this.y = y;
this.size = Math.random()*20+5;
this.dx = Math.random()*4-2;
this.dy = Math.random()*4-2;
this.color = color;
this.shape = possibleShapes[Math.floor(Math.random()*possibleShapes.length)];
}
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext("2d");
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
resizeCanvas();
canvas.onclick = function(event) {
handleClick(event.clientX, event.clientY);
};
timer = setInterval(resizeCanvas, 20);
timerTwo = setInterval(newShape, 200);
}
function newShape() {
var x = Math.random() * canvas.width;
var y = Math.random() * canvas.height;
var colors = ["red", "green", "blue", "orange", "purple", "yellow"];
var color = colors[Math.floor(Math.random()*colors.length)];
shapes.push(new Shape(x, y, color));
}
function drawCircle(circle) {
context.beginPath();
context.arc(circle.x, circle.y, circle.size, 0, degreesToRadians(360), true);
context.fillStyle = circle.color;
context.fill();
}
function drawSquare(square) {
context.beginPath();
context.fillStyle = square.color;
context.fillRect(square.x, square.y, square.size, square.size);
}
function drawTriangle(triangle) {
context.beginPath();
context.fillStyle = triangle.color;
context.moveTo(triangle.x+triangle.size,triangle.y);
context.lineTo(triangle.x,triangle.y);
context.lineTo(triangle.x,triangle.y+triangle.size);
context.closePath();
context.fill();
}
function drawCloud(cloud) {
context.beginPath();
context.moveTo(cloud.x, cloud.y);
context.bezierCurveTo(cloud.x-40, cloud.y+20, cloud.x-40, cloud.y+70, cloud.x+60, cloud.y+70);
context.bezierCurveTo(cloud.x+80, cloud.y+100, cloud.x+170, cloud.y+100, cloud.x+170, cloud.y+70);
context.bezierCurveTo(cloud.x+250, cloud.y+70, cloud.x+250, cloud.y+40, cloud.x+210, cloud.y+20);
context.bezierCurveTo(cloud.x+260, cloud.y-40, cloud.x+200, cloud.y+50, cloud.x+170, cloud.y-30);
context.bezierCurveTo(cloud.x+150, cloud.y-75, cloud.x+80, cloud.y-60, cloud.x+80, cloud.y-30);
context.bezierCurveTo(cloud.x+30, cloud.y-75, cloud.x-20, cloud.y-60, cloud.x, cloud.y);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.strokeStyle = cloud.color;
context.stroke();
}
function drawDrop(drop) {
context.beginPath();
context.lineJoin = 'miter';
context.moveTo(drop.x, drop.y);
context.arc(drop.x, drop.y+68, 34.5, 5.75, 3.66, false);
context.quadraticCurveTo(drop.x-3.5, drop.y+15, drop.x, drop.y);
context.closePath();
context.lineWidth = 2;
context.fillStyle = drop.color;
context.fill();
}
function drawText() {
context.fillStyle = 'white';
context.font = 'bold 2em sans-serif';
context.textAlign = 'right';
context.fillText('Art?', canvas.width-40, canvas.height-40);
}
function resizeCanvas() {
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
fillBackgroundColor();
for (var i=0; i<shapes.length; i++) {
if (shapes[i].shape == 'square') {
drawSquare(shapes[i]);
} else if (shapes[i].shape == 'circle') {
drawCircle(shapes[i]);
} else if (shapes[i].shape == 'triangle') {
drawTriangle(shapes[i]);
} else if (shapes[i].shape == 'drop') {
drawDrop(shapes[i]);
} else if (shapes[i].shape == 'cloud') {
drawCloud(shapes[i]);
}
if (shapes[i].x + shapes[i].dx > canvas.width || shapes[i].x + shapes[i].dx < 0)
shapes[i].dx = -shapes[i].dx;
if (shapes[i].y + shapes[i].dy > canvas.height || shapes[i].y + shapes[i].dy < 0)
shapes[i].dy = -shapes[i].dy;
shapes[i].x += shapes[i].dx;
shapes[i].y += shapes[i].dy;
}
drawText();
}
function fillBackgroundColor() {
//var colors = ["white", "yellow", "blue", "red"];
//var bgColor = colors[Math.floor(Math.random() * colors.length)];
context.fillStyle = 'black';
context.fillRect(0, 0, canvas.width, canvas.height);
}
function degreesToRadians(degrees) {
//converts from degrees to radians and returns
return (degrees * Math.PI)/180;
}
window.onload = init;
You can translate entire canvas instead of modifying your code.
let's suppose that bolt is an object with x and y as properties.
function drawBolt(bolt){
context.save();
context.translate(bolt.x, bolt.y);
context.beginPath()
context.moveTo(140,28);
context.lineTo(164,28);
context.moveTo(164,28);
context.lineTo(138,53);
context.moveTo(138,53);
context.lineTo(157,53);
context.moveTo(157,53);
context.lineTo(122,81);
context.moveTo(122,81);
context.lineTo(137,82);
context.moveTo(137,82);
context.lineTo(93,105);
context.moveTo(93,105);
context.lineTo(109,87);
context.moveTo(109,87);
context.lineTo(100,87);
context.moveTo(100,87);
context.moveTo(126,61);
context.lineTo(110,60);
context.moveTo(110,60);
context.lineTo(140,28);
context.closePath();
context.fill();
context.restore();
};
This is equivalent to drawing the bolt modifying all the points adding x and y to each of them.
Related
I have this jsfiddle
http://jsfiddle.net/t9L6g3bd/4/
// requestAnimationFrame Shim
(function () {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var endPercent = 101;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
context.lineWidth = 2;
context.strokeStyle = '#333';
animate();
function animate(current) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc++;
if (curPerc < endPercent) {
requestAnimationFrame(function () {
animate(curPerc / 100)
});
} else {
ex(126, 126);
cross(126, 126);
//fadein(0);
}
}
function fadein(a) {
context.lineWidth = 1.5;
context.globalAlpha = a;
context.beginPath();
context.moveTo(166, 84);
context.lineTo(84, 166);
context.stroke();
context.beginPath();
context.moveTo(166, 166);
context.lineTo(84, 84);
context.stroke();
if (a != 0.8) {
requestAnimationFrame(function () {
fadein(a + 0.01);
});
}
}
function ex(x, y) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(84, x);
context.lineTo(168, y);
context.stroke();
if (x != 168) {
requestAnimationFrame(function () {
ex(x + 1, y - 1)
});
}
}
function cross(x, y) {
// context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(84, x);
context.lineTo(168, y);
context.stroke();
if (x != 84) {
requestAnimationFrame(function () {
cross(x - 1, y + 1)
});
}
}
I was wondering if there was a way to combine the circle animation and the x at the same time, or one after the other so that they both are on the screen and both have smooth edges
You needed to refactor your code.
Link to refactored jsfiddle
function animate() {
if (curPerc < endPercent) {
context.clearRect(0, 0, canvas.width, canvas.height);
drawCircle(curPerc / 100);
fadeIn(curPerc / 100);
curPerc++;
requestAnimationFrame(function () {
animate();
});
}
}
Basically you needed to change your code so that only one animation loop is running, and on each loop iteration call an update function for each animation. I would say though, that the code overall is kind of difficult to maintain and you should consider further refactoring to rectify this. Hope this helps.
You should indeed use only one requestAnimationFrame, because its overhead is quite big, but mainly for the clarity of your code (hard to know as it is which object is animating or not).
-->> What about storing all the animation data into objects, and even letting the object animate / draw themselves ?
This way you have a clear separation of concerns, and changing one aspect of the animation is much easier.
I started to do this in this fiddle :
http://jsfiddle.net/0200h552/6/
the animation loop becomes quite simple :
function animate() {
requestAnimationFrame(animate);
context.clearRect(0, 0, canvas.width, canvas.height);
//
circle.draw();
if (!circle.animate()) {
ex.draw();
cross.draw();
ex.animate();
cross.animate();
}
}
And here are the three objects in use :
var circle = {
x: centerX,
y: centerY,
radius: 75,
curPerc: 0,
endPercent: 101,
animate: function () {
if (this.curPerc < this.endPercent) {
this.curPerc++;
return true;
}
return false;
},
draw: function () {
var perc = this.curPerc / this.endPercent;
var oldAlpha = context.globalAlpha;
context.globalAlpha = perc;
context.beginPath();
context.arc(this.x, this.y, this.radius, -(quart), ((circ) * perc) - quart, false);
context.stroke();
context.globalAlpha = oldAlpha;
}
};
The "ex" :
var ex = {
x: centerX,
y: centerY,
animate: function () {
if (this.x != 168) {
this.x++;
this.y--;
return true;
}
return false;
},
draw: function () {
var x = this.x;
var y = this.y;
context.beginPath();
context.moveTo(84, x);
context.lineTo(168, y);
context.stroke();
}
};
The cross :
var cross = {
x: centerX,
y: centerY,
animate: function () {
if (this.x != 84) {
this.x--;
this.y++;
return true;
}
return false;
},
draw: function () {
var x = this.x;
var y = this.y;
context.beginPath();
context.moveTo(84, x);
context.lineTo(168, y);
context.stroke();
}
};
i have problem i have background image and changing it scale and position with mousewheel and can drawing with mousedown and mousemove events. me example: http://jsfiddle.net/74MCQ/ Now see first drawing and second zoom we don't see drawing lines. I need make like a paint if drawing on me select position and if zoom i need see equal position with equal zoom scale.
You need a way to store the drawings of your user, either within another canvas, or by storing coordinates.
I suggest you store coordinates, below here's some code that will store the lines within an array, each line being an array of coordinates like : [x0, y0, x1, y1, x2, y2, ... ].
Edit : now i simplified the things, the coordinates are stored relative to the center of canvas.
See the fiddle, it is mostly working.
fiddle :
http://jsfiddle.net/gamealchemist/74MCQ/4/
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
var x = evt.clientX - rect.left;
var y = evt.clientY - rect.top;
var sx = (x-cw/2)/scale;
var sy = (y-ch/2)/scale;
return {
x: x,
y: y,
sx : sx,
sy:sy
};
}
/****** PAINT ******/
var isDrawing = false;
var color = "#000000";
var brushWidth = 10;
//var previousEvent = false;
ctx.strokeStyle = '#000000';
var currentLine = null;
var allLines = [];
$("#canvas").mousedown(function (e) {
var mousePos = getMousePos(canvas, e);
ctx.moveTo(mousePos.x, mousePos.y);
isDrawing = true;
if (currentLine) allLines.push(currentLine);
currentLine = [];
currentLine.push(mousePos.sx, mousePos.sy);
});
$("#canvas").mouseup(function () {
isDrawing = false;
if (currentLine) allLines.push(currentLine);
currentLine = null;
});
$("#canvas").mouseout(function () {
isDrawing = false;
if (currentLine) allLines.push(currentLine);
currentLine = null;
});
$("#canvas").mousemove(function (e) {
if (isDrawing === true) {
var mousePos = getMousePos(canvas, e);
currentLine.push(mousePos.sx, mousePos.sy);
//paint tools, effects
ctx.lineWidth = 10;
ctx.strokeStyle = color;
ctx.shadowBlur = 1;
ctx.shadowColor = 'rgb(0, 0, 0)';
ctx.lineTo(mousePos.x, mousePos.y);
ctx.stroke();
}
});
function drawStoredLines() {
var thisLine;
for (var i = 0; i < allLines.length; i++) {
thisLine = allLines[i];
drawLine(thisLine);
}
}
function drawLine(ptArray) {
if (ptArray.length <= 2) return;
ctx.beginPath();
ctx.moveTo(ptArray[0], ptArray[1]);
for (var p = 2; p < ptArray.length; p += 2) {
ctx.lineTo(ptArray[p], ptArray[p + 1]);
}
ctx.lineWidth = 10;
ctx.strokeStyle = color;
ctx.shadowBlur = 1;
ctx.shadowColor = 'rgb(0, 0, 0)';
ctx.stroke();
}
Notice that i couldn't resist reducing your 175 lines code to select the scale to a 25 lines one :-)
var zoomSteps = [0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 1.5, 2.0, 3.0, 4.0];
var zoomIndex = zoomSteps.indexOf(1);
function doScroll(e) {
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
zoomIndex = zoomIndex + delta;
if (zoomIndex < 0) zoomIndex = 0;
if (zoomIndex >= zoomSteps.length) zoomIndex = zoomSteps.length - 1;
scale = zoomSteps[zoomIndex];
imageWidthZoomed = imageWidth * scale;
imageHeightZoomed = imageHeight * scale;
var mousePos = getMousePos(canvas, e);
draw(mousePos.x, mousePos.y, scale);
}
I've created this animation for my project that had to use any form of physics.
I am a total beginner, too :) Anyway, this is my project now :
Bouncing Balls
You can setup gravity and force, then click play, and just drag and drop to shoot the balls. You can change the values and hit update too see an effect.
My question is, how can I create an effect that when I press ratio button (for example) I can see the path that ball makes? Is it complicated? As I was saying I am a beginner, so no complex code for me :)
Also, doyou have any ideas to make the project better? Any additional "physics" effects? Or maybe you know a website that shows tutorials for simile (please) effects made in HTML5/js so I can add additional effects to my project.
One possibility (as you're clearing the canvas each frame) would be to draw ball paths onto a secondary canvas, which would not be cleared each frame. Then, when you come to clear the first frame, render the second frame after clearing, and before rendering the balls.
The second canvas would of course have to be the same dimensions as the first, so that all of the ball points line up correctly. The second canvas should also have a z-index lower than the first, so that it is only shown when you specifically render it to the first canvas (i.e. when the radio button is checked).
To decrease any lag while the radio is not checked, you could skip drawing the ball paths to the second canvas, although I don't think you would see any great increase in performance.
On each frame update, you would mark the position of each ball with a pixel, or line (from the previous position to the current) on the second canvas.
Looking at your code, you seem pretty competent, so I've skipped writing an example as I think this would be good experience for you :)
Modified 'script.js' source demonstrating solution
window.onload = function(){
$("#canvas").hide();
var howManyPaths = 0;
var showPath=false;
// SLIDERS
var gravitySlider = document.getElementById('gravitySlider');
var gravityVal = document.getElementById('gravityValue');
gravitySlider.onchange = function(){
gravityVal.value = gravitySlider.value;
}
gravityVal.onkeyup = function(){
gravitySlider.value = gravityVal.value;
}
var forceSlider = document.getElementById('forceSlider');
var forceValue = document.getElementById('forceValue');
forceSlider.onchange = function(){
forceValue.value = forceSlider.value;
}
forceValue.onkeyup = function(){
forceSlider.value = forceValue.value;
}
// GLOBAL VARIABLES
var test = false;
var gravityCount = $("#gravity").val();
var forceCount = $("#rectangles").val();
// CSS :
var playCSS = document.getElementById("play");
var restartCSS = document.getElementById("restart");
var clickableCSS = document.getElementById("setup");
var clickableBG = document.getElementById("img");
//restartCSS.style.visibility="hidden";
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");
//var ctx;
var gravity = 9.86;
var forceFactor = 0.5;
var mouseDown = false;
var balls = new Array();
var mousePos = new Array();
// EVENT HANDLER
function onMouseDown(evt){
mouseDown = true;
mousePos['downX'] = evt.pageX;
mousePos['downY'] = evt.pageY;
}
function onMouseUp(evt){
mouseDown = false;
setup.style.visibility="visible";
if(test == true && !( mousePos['downX'] < 200 && mousePos['downY'] < 150) ){
restartCSS.style.visibility="visible";
forceFactor = forceCount;
balls.push(new ball(mousePos["downX"],
mousePos["downY"],
(evt.pageX - mousePos["downX"]) * forceFactor,
(evt.pageY - mousePos["downY"]) * forceFactor,
10 + (Math.random() * 10),
0.8,
randomColor()
));
}
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
}
function onMouseMove(evt){
mousePos['currentX'] = evt.pageX;
mousePos['currentY'] = evt.pageY;
}
function resizeWindow(evt){
//canvas.height = 960;
//canvas.width = 720;
canvas.height = $(window).height()-6;
canvas.width = $(window).width();
canvas2.height = $(window).height()-6;
canvas2.width = $(window).width();
}
$(document).mousedown(onMouseDown);
$(document).mouseup(onMouseUp);
$(document).mousemove(onMouseMove);
$(window).bind("resize", resizeWindow);
// GRAPHICS CODE
function circle(x, y, r, col){
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2, true);
ctx.closePath;
// fill
ctx.fillStyle = col;
ctx.fill();
// stroke
ctx.lineWidth = r * 0.1;
ctx.strokeStyle = "#000000";
ctx.stroke();
}
function circlePath(x, y)
{
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.fillStyle = '#3f4043';
ctx2.fillRect(x, y, 5, 5);
ctx2.strokeStyle = "black";
ctx2.strokeRect(x, y, 5, 5);
}
function randomColor(){
var letter = "0123456789ABCDEF".split("");
var color = "#";
for(var i=0; i<6; i++){
color += letter[Math.round(Math.random()*15)];
}
return color;
}
function arrow(fromX, fromY, toX, toY, color){
// path
ctx.beginPath();
var headLen = 10;
var angle = Math.atan2(toY - fromY, toX - fromX);
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.lineTo(toX - headLen * Math.cos(angle - Math.PI/6), toY - headLen * Math.sin(angle - Math.PI/6));
ctx.moveTo(toX, toY);
ctx.lineTo(toX - headLen * Math.cos(angle + Math.PI/6), toY - headLen * Math.sin(angle + Math.PI/6));
// style
ctx.lineWith = 1;
ctx.strokeStyle = color;
ctx.lineCap = "butt";
ctx.stroke();
}
function drawBall(){
// Gravity
gravity = gravityCount;
this.speedY += gravity * 0.5; // v = a * t
this.x += this.speedX * 0.05; // s = v * t
this.y += this.speedY * 0.05;
// prawa ściana
if(this.x + this.r > canvas.width){
this.x = canvas.width - this.r;
this.speedX *= -1 * this.bounce;
}
// lewa ściana
if(this.x - this.r < 0){
this.x = this.r;
this.speedX *= -1 * this.bounce;
}
// dolna ściana
if(this.y + this.r > canvas.height){
this.y = canvas.height - this.r;
this.speedY *= -1 * this.bounce;
}
// górna ściana
if(this.y - this.r < 0){
this.y = this.r;
this.speedY *= -1 * this.bounce;
}
// zwalnianie na ziemi
if (this.speedX > 0.25){
this.speedX -= 0.25;
if (this.speedY > 0.25)
this.speedY -= 0.25;
}
if (this.speedX < -0.25){
this.speedX += 0.25;
//if (this.speedY < -0.25)
// this.speedY += 0.25;
}
circle(this.x, this.y, this.r, this.col);;
}
// OBJECTS
function ball(positionX, positionY, sX, sY, radius, b, color){
this.x = positionX;
this.y = positionY;
this.speedX = sX;
this.speedY = sY;
this.r = radius;
this.bounce = b;
this.col = color;
this.draw = drawBall;
}
//GAME LOOP
function gameLoop(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
//grab the context from your destination canvas
//if path drawing is enabled, first draw the path canvas to the display canvas
if (showPath) ctx.drawImage(canvas2,0,0);
if(mouseDown == true){
// ctx.clearRect(0, 0, canvas.width, canvas.height); /* !important !!!!!!!!!!!!!!! */
arrow(mousePos['downX'], mousePos['downY'], mousePos['currentX'], mousePos['currentY'], "red");
}
for(var i=0; i<balls.length; i++){
balls[i].draw();
if (i==balls.length-1) {
//draw path
ctx2.fillStyle = '#3f4043';
ctx2.fillRect(balls[i].x, balls[i].y, 5, 5);
ctx2.strokeStyle = "black";
ctx2.strokeRect(balls[i].x, balls[i].y, 5, 5);
}
}
ctx.fillStyle = "#000000";
ctx.font = "15px Arial";
ctx.fillText("Balls: " + balls.length + " " + gravityCount + " " + forceCount + " " + howManyPaths, 10, canvas.height -10);
}
// START THE GAME
function init(){
//$("#setup").hide();
$("#canvas").show();
$("#canvas2").hide();
ctx = $('canvas')[0].getContext("2d");
canvas.height = $(window).height()-6;
canvas.width = $(window).width();
//canvas.width = 960;
//canvas.height = 720;
canvas2.height = $(window).height()-6;
canvas2.width = $(window).width();
return setInterval(gameLoop, 10);
}
$("#play").click(function() {
test = true;
playCSS.style.visibility="hidden";
gravityCount = $("#gravitySlider").val();
forceCount = $("#forceSlider").val();
init();
});
$("#restart").click(function() {
window.location.href="index.html";
});
$("#refresh").click(function() {
gravityCount = $("#gravitySlider").val();
forceCount = $("#forceSlider").val();
});
$("#showPath").click(function() {
showPath=true;
});
$("#hidePath").click(function() {
showPath=false;
});
}
I'm having trouble keeping one object on my canvas. The initially drawn box rendered it in the correct position, but it disappears when I drag it:
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
eraseAllButton = document.getElementById('eraseAllButton'),
strokeStyleSelect = document.getElementById('strokeStyleSelect'),
guidewireCheckbox = document.getElementById('guidewireCheckbox'),
drawingSurfaceImageData,
mousedown = {},
rubberbandRect = {},
dragging = false,
guidewires = guidewireCheckbox.checked,
w = 90, h = 90;
count = 0;
boxesXCo = 0;
boxesYCo = 0;
i = 0;
// Functions..........................................................
function drawGrid(color, stepx, stepy) {
context.save()
context.strokeStyle = color;
context.lineWidth = 0.5;
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
context.beginPath();
context.moveTo(i, 0);
context.lineTo(i, context.canvas.height);
context.stroke();
}
for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
}
context.restore();
}
function windowToCanvas(x, y) {
var bbox = canvas.getBoundingClientRect();
return { x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height) };
}
// Save and restore drawing surface...................................
function saveDrawingSurface() {
drawingSurfaceImageData = context.getImageData(0, 0,
canvas.width,
canvas.height);
}
function restoreDrawingSurface() {
context.putImageData(drawingSurfaceImageData, 0, 0);
}
function drawRubberbandShape(loc) {
context.beginPath();
context.moveTo(mousedown.x, mousedown.y);
//context.lineTo(loc.x, loc.y);
context.stroke();
}
function updateRubberband(loc) {
//updateRubberbandRectangle(loc);
context.restore();
drawRubberbandShape(loc);
}
// Guidewires.........................................................
function drawHorizontalLine (y) {
context.beginPath();
context.moveTo(0,y+0.5);
context.lineTo(context.canvas.width,y+0.5);
context.stroke();
}
function drawVerticalLine (x) {
context.beginPath();
context.moveTo(x+0.5,0);
context.lineTo(x+0.5,context.canvas.height);
context.stroke();
}
function drawGuidewires(x, y) {
context.save();
context.strokeStyle = 'rgba(0,0,230,0.4)';
context.lineWidth = 0.5;
drawVerticalLine(x);
drawHorizontalLine(y);
context.restore();
}
// Canvas event handlers..............................................
canvas.onmousedown = function (e) {
var loc = windowToCanvas(e.clientX, e.clientY);
e.preventDefault(); // prevent cursor change
context.restore();
saveDrawingSurface();
mousedown.x = loc.x;
mousedown.y = loc.y;
dragging = true;
if (i ==0)
i++;
else if(((mousedown.x<=(boxesXCo+w)&&(mousedown.x>=boxesXCo))&&
((mousedown.y<=(boxesYCo+h)&&(mousedown.y>=boxesYCo)))))
i--;
};
canvas.onmousemove = function (e) {
var loc;
if (dragging) {
e.preventDefault(); // prevent selections
loc = windowToCanvas(e.clientX, e.clientY);
restoreDrawingSurface();
//updateRubberband(loc);
if(guidewires) {
drawGuidewires(loc.x, loc.y);
}
}
if(((mousedown.x<=(boxesXCo+w)&&(mousedown.x>=boxesXCo))&&
((mousedown.y<=(boxesYCo+h)&&(mousedown.y>=boxesYCo))))
&& (dragging)&&(i == 1 )){
context.restore();
restoreDrawingSurface();
context.fillStyle = strokeStyleSelect.value;
context.fillRect(e.clientX,e.clientY,w,h);
};
//Trying to implement moving shapes but need to store values of drawn objs
};
canvas.onmouseup = function (e) {
loc = windowToCanvas(e.clientX, e.clientY);
restoreDrawingSurface();
updateRubberband(loc);
dragging = false;
if(i == 0);
else {
saveDrawingSurface();
restoreDrawingSurface();
context.fillRect(e.clientX,e.clientY, w, h);
boxesXCo = e.clientX;
boxesYCo = e.clientY;
context.restore();
i++;}
/*else if(i == 1)
{
context.restore();
}*/
//context.fillRect(mousedown.x,mousedown.y,w,h,"FF0982");
};
// Controls event handlers.......................................
eraseAllButton.onclick = function (e) {
context.clearRect(0, 0, canvas.width, canvas.height);
drawGrid('lightgray', 10, 10);
saveDrawingSurface();
count =0;
context.restore();
};
strokeStyleSelect.onchange = function (e) {
context.strokeStyle = strokeStyleSelect.value;
context.fillStyle = strokeStyleSelect.value;
};
guidewireCheckbox.onchange = function (e) {
guidewires = guidewireCheckbox.checked;
};
// Initialization................................................
context.strokeStyle = strokeStyleSelect.value;
context.fillStyle = strokeStyleSelect.value;
drawGrid('lightgray', 10, 10);
//context.fillRect(mousedown.x,mousedown.y,(mousedown.x+50),(mousedown.x+50),"FF0982");
//context.drawRect(mousedown.x-50,mousedown.y-50,mousedown.x+50,mousedown.y+50);
thanx again
Rather than drawing to canvas on each mouse movement, use window.requestFrameAnimation to draw constantly.
At a guess, I'd assume either the browser rendering is interfering or the coordinates are out but I can't run your code to make sure.
I've written some pseudo code that shows what I do for rendering things. You'll need to implement this for yourself, it won't run out of the box, it's just intended as a guide.
var Box = function() {
};
Box.prototype = {
x: 0,
y: 0,
draw: function (canvas) {
// draw the item on the canvas
}
};
var box = new Box();
window.requestAnimationFrame(function() {
box.draw(canvas);
window.requestAnimationFrame();
});
canvas.onmousemove = function(e) {
if (dragging) {
box.x = e.clientX;
box.y = e.clientY;
}
}
I have a html5 canvas that draws a sound wave. I have set the background as an background image, however, I want this background image to repeat. Can anyone tell me how I would do this and what I need to add into my code:
var backgroundImage = new Image();
backgroundImage.src = 'http://www.samskirrow.com/client-kyra/images/main-bg.jpg';
var canvas;
var context;
function init(c) {
canvas = document.getElementById(c);
context = canvas.getContext("2d");
soundManager.onready(function() {
initSound(clientID, playlistUrl);
});
aniloop();
}
function aniloop() {
requestAnimFrame(aniloop);
drawWave();
}
function drawWave() {
var step = 10;
var scale = 60;
// clear
context.drawImage(backgroundImage, 0, 0);
// left wave
context.beginPath();
context.moveTo(0, 256);
for ( var i = 0; i < 256; i++) {
context.lineTo(6 * i, 257 + waveLeft[i] * 80.);
}
context.lineWidth = 1;
context.strokeStyle = "#000";
context.stroke();
// right wave
context.beginPath();
context.moveTo(0, 256);
for ( var i = 0; i < 256; i++) {
context.lineTo(6 * i, 256 + waveRight[i] * 80.);
}
context.lineWidth = 1;
context.strokeStyle = "#000";
context.stroke();
}
function updateWave(sound) {
waveLeft = sound.waveformData.left;
}
return {
init : init
};
})();
You can see this code in action here:
http://www.samskirrow.com/client-kyra
Use the canvas' createPattern function
const canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = 'https://www.google.nl/images/srpr/logo3w.png';
img.addEventListener('load', () => {
const ptrn = context.createPattern(img, 'repeat'); // Create a pattern with this image, and set it to "repeat".
context.fillStyle = ptrn;
context.fillRect(0, 0, canvas.width, canvas.height); // context.fillRect(x, y, width, height);
})
<canvas id="canvas" width="600px" height="600px"></canvas>
(This is the fastest of the 2 samples).
Or, try a manual implementation:
const canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = 'https://www.google.nl/images/srpr/logo3w.png';
img.addEventListener('load', () => {
for (let w = 0; w < canvas.width; w += img.width) {
for (let h = 0; h < canvas.height; h += img.height) {
context.drawImage(img, w, h);
}
}
})
<canvas id="canvas" width="600px" height="600px"></canvas>