Currently I'm creating a sheet of graph paper with the canvas object in HTML5. I'm able to create the canvas as well as fill in the selected areas with a color by finding the x/y position. Unfortunately I'm having some troubles using the jQuery mousemove method to display a pop-up of the information selected for the square.
Here's my code:
Canvas Creation/Layout:<br>
<script type="text/javascript">
var canvas;
var context;
var color;
var state;
var formElement;
var number = 0;
function showGrid()
{
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
context.lineWidth=0.5;
context.strokeStyle='#999999';
lineSpacing=10;
var xPos = 0;
var yPos = 0;
var numHorizontalLines = parseInt(canvas.height/lineSpacing);
var numVerticalLines = parseInt(canvas.width/lineSpacing);
state = new Array(numHorizontalLines);
for (var y = 0; y < numHorizontalLines; ++y)
{
state[y] = new Array(numVerticalLines);
}
for(var i=1; i<=numHorizontalLines;i++)
{
yPos=i*lineSpacing;
context.moveTo(0,yPos);
context.lineTo(canvas.width,yPos);
context.stroke;
}
for(var i=1; i<=numVerticalLines; i++)
{
xPos=i*lineSpacing;
context.moveTo(xPos,0);
context.lineTo(xPos,canvas.height);
context.stroke();
}
}
function fill(s, gx, gy)
{
context.fillStyle = s;
context.fillRect(gx * lineSpacing, gy * lineSpacing, lineSpacing, lineSpacing);
if(s != null)
{
}
}
function getPosition(e)
{
var x = new Number();
var y = new Number();
var canvas = document.getElementById("canvas");
if (e.pageX || e.pageY)
{
x = e.pageX;
y = e.pageY;
}
else
{
x = e.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
x -= canvas.offsetLeft;
y -= canvas.offsetTop;
var gx = Math.floor((x / lineSpacing));
var gy = Math.floor((y / lineSpacing));
state[gy][gx] = true;
fill(color, gx, gy);
addNumber();
}
HTML:
<div class="graphpaper" id="graphpaper" onclick="getPosition(event)" style="width:956px; height:1186px;">
<img src="images/PosterBorder_Top.png" align="right"/>
<img src="images/posterBorder_left.png" align="left" valign="top"/>
<canvas id ="canvas" width = "920" height = "1160" align="left">
</canvas>
</div>
<!-- HIDDEN / POP-UP DIV -->
<div id="pop-up">
<h3>Pop-up div Successfully Displayed</h3>
<p>
This div only appears when the trigger link is hovered over.
Otherwise it is hidden from view.
</p>
</div>
jQuery for Pop-Up display:
$('#canvas').mousemove(function(event){
console.log("Here I am!");
$('div#pop-up').show().appendTo('body');
});
Any suggestions? I'm obviously missing something but from what I've done this should work I believe.
Related
Below is a script which defines two functions that draw 4 rectangular buttons and 1 circular button respectively. I am trying to implement specific Hover and Click functionality into the buttons (as described in the script alerts) but I am at a bit of a loss as to how to do this. I tried calling the makeInteractiveButton() functions on each click but this caused a lot of odd overlap and lag. I want the script to do the following:
If the circular button is hovered, I would like it's fillColour to change and if it is clicked I would like it to change again to the colours described in the code (#FFC77E for hover, #FFDDB0 for clicked). This should only happen for the duration of the hover or click.
HTML:
<html lang="en">
<body>
<canvas id="game" width = "750" height = "500"></canvas>
<script type='text/javascript' src='stack.js'></script>
</body>
</html>
JavaScript:
var c=document.getElementById('game'),
canvasX=c.offsetLeft,
canvasY=c.offsetTop,
ctx=c.getContext('2d')
elements = [];
c.style.background = 'grey';
function makeInteractiveButton(x, strokeColor, fillColor) {
ctx.strokeStyle=strokeColor;
ctx.fillStyle=fillColor;
ctx.beginPath();
ctx.lineWidth=6;
ctx.arc(x, 475, 20, 0, 2*Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fill();
elements.push({
arcX: x,
arcY: 475,
arcRadius: 20
});
}
b1 = makeInteractiveButton(235, '#FFFCF8', '#FFB85D');
c.addEventListener('mousemove', function(event) {
x=event.pageX-canvasX; // cursor location
y=event.pageY-canvasY;
elements.forEach(function(element) {
if (x > element.left && x < element.left + element.width &&
y > element.top && y < element.top + element.height) { // if cursor in rect
alert('Rectangle should undergo 5 degree rotation and 105% scale');
}
else if (Math.pow(x-element.arcX, 2) + Math.pow(y-element.arcY, 2) <
Math.pow(element.arcRadius, 2)) { // if cursor in circle
alert('Set b1 fillColour to #FFC77E.');
}
});
}, false);
c.addEventListener('click', function(event) {
x=event.pageX-canvasX; // cursor location
y=event.pageY-canvasY;
elements.forEach(function(element) {
if (x > element.left && x < element.left + element.width &&
y > element.top && y < element.top + element.height) { // if rect clicked
alert('Move all cards to centre simultaneously.');
}
else if (Math.pow(x-element.arcX, 2) + Math.pow(y-element.arcY, 2) <
Math.pow(element.arcRadius, 2)) { // if circle clicked
alert('Set b1 fillColour to #FFDDB0.');
}
});
}, false);
One way is keep all element data and write a hitTest(x,y) function but when you have a lot of complex shapes its better to use a secondary canvas to render element with their ID instead of their color in it and the color of x,y in second canvas is ID of hitted element, I should mention that the second canvas is'nt visible and its just a gelper for get the hitted element.
Github Sample:
https://siamandmaroufi.github.io/CanvasElement/
Simple implementation of hitTest for Rectangles :
var Rectangle = function(id,x,y,width,height,color){
this.id = id;
this.x=x;
this.y=y;
this.width = width;
this.height = height;
this.color = color || '#7cf';
this.selected = false;
}
Rectangle.prototype.draw = function(ctx){
ctx.fillStyle = this.color;
ctx.fillRect(this.x,this.y,this.width,this.height);
if(this.selected){
ctx.strokeStyle='red';
ctx.setLineDash([5,5]);
ctx.lineWidth = 5;
ctx.strokeRect(this.x,this.y,this.width,this.height);
}
}
Rectangle.prototype.hitTest=function(x,y){
return (x >= this.x) && (x <= (this.width+this.x)) &&
(y >= this.y) && (y <= (this.height+this.y));
}
var Paint = function(el) {
this.element = el;
this.shapes = [];
}
Paint.prototype.addShape = function(shape){
this.shapes.push(shape);
}
Paint.prototype.render = function(){
//clear the canvas
this.element.width = this.element.width;
var ctx = this.element.getContext('2d');
for(var i=0;i<this.shapes.length;i++){
this.shapes[i].draw(ctx);
}
}
Paint.prototype.setSelected = function(shape){
for(var i=0;i<this.shapes.length;i++){
this.shapes[i].selected = this.shapes[i]==shape;
}
this.render();
}
Paint.prototype.select = function(x,y){
for(var i=this.shapes.length-1;i>=0;i--){
if(this.shapes[i].hitTest(x,y)){
return this.shapes[i];
}
}
return null;
}
var el = document.getElementById('panel');
var paint = new Paint(el);
var rectA = new Rectangle('A',10,10,150,90,'yellow');
var rectB = new Rectangle('B',150,90,140,100,'green');
var rectC = new Rectangle('C',70,85,200,70,'rgba(0,0,0,.5)');
paint.addShape(rectA);
paint.addShape(rectB);
paint.addShape(rectC);
paint.render();
function panel_mouseUp(evt){
var p = document.getElementById('panel');
var x = evt.x - p.offsetLeft;
var y = evt.y - p.offsetTop;
var shape = paint.select(x,y);
if(shape){
alert(shape.id);
}
//console.log('selected shape :',shape);
}
function panel_mouseMove(evt){
var p = document.getElementById('panel');
var x = evt.x - p.offsetLeft;
var y = evt.y - p.offsetTop;
var shape = paint.select(x,y);
paint.setSelected(shape);
}
el.addEventListener('mouseup',panel_mouseUp);
el.addEventListener('mousemove',panel_mouseMove);
body {background:#e6e6e6;}
#panel {
border:solid thin #ccc;
background:#fff;
margin:0 auto;
display:block;
}
<canvas id="panel" width="400px" height="200px" >
</canvas>
just click or move over the shapes
I have a canvas on which I place textObjects (array of Text()) which are drawn on the canvas. I'm able to move these objects individually and upon selection (and in debug I can see that) the object is saved in a global variable called mySel.
My problem is that once I click the button (#btn-bold) my globale variables textObjects and mySel are both undefined. On button click I want to loop through my list of textObjects and edit the fontStyle of the textObject with the same position as mySel.
Why does this happen and how can I fix this. I call and set the global variables in other functions but when I call for the click function they are undefined.
Add Text is called from a JQuery modal dialog button. The Canvas is refreshed every 20ms using the function setInterval(draw, 20) in the init()
I provided the code that's responsible for adding to the list, drawing the list and mouse movement. If the initialize and/or initialization of variables are needed I'll post them.
Javascript
function Text() {
this.text = "Hallo";
this.x = 0;
this.y = 0;
this.fillColor = "black";
this.fontFamily = "Arial";
this.fontStyle = "normal";
this.fontSize = "18pt";
this.fontWeight = "normal";
}
function addText(text, fillColor, fontSize, fontFamily, fontStyle, fontWeight, x, y) {
var textTemp = new Text;
textTemp.text = text;
textTemp.fillColor = fillColor;
textTemp.fontSize = fontSize;
textTemp.fontFamily = fontFamily;
textTemp.fontWeight = fontWeight;
textTemp.fontStyle = fontStyle;
textTemp.x = x;
textTemp.y = y;
textObjects.push(textTemp);
invalidate();
}
var textObjects = [];
var mySel;
function drawText(context, textObject) {
if (textObject.x > WIDTH || textObject.y > HEIGHT) return;
if (textObject.x < 0 || textObject.y < 0) return;
context.fillStyle = textObject.fillColor;
context.font = textObject.fontWeight + " " + textObject.fontSize + " " + textObject.fontFamily;
context.fillText(textObject.text, textObject.x, textObject.y);
}
// Happens when the mouse is moving inside the canvas
function myMove(e) {
if (isDrag) {
getMouse(e);
mySel.x = mx - offsetx;
mySel.y = my - offsety;
// something is changing position so we better invalidate the canvas!
invalidate();
}
}
function myDown(e) {
getMouse(e);
clear(gctx);
var lText = textObjects.length;
for (var i = lText - 1; i >= 0; i--) {
// draw shape onto ghost context
drawText(gctx, textObjects[i]);
// get image data at the mouse x,y pixel
var imageData = gctx.getImageData(mx, my, 1, 1);
var index = (mx + my * imageData.width) * 4;
// if the mouse pixel exists, select and break
if (imageData.data[3] > 0) {
mySel = textObjects[i];
offsetx = mx - mySel.x;
offsety = my - mySel.y;
mySel.x = mx - offsetx;
mySel.y = my - offsety;
isDrag = true;
canvas.onmousemove = myMove;
invalidate();
clear(gctx);
alertSelected();
return;
}
}
// havent returned means we have selected nothing
mySel = null;
// clear the ghost canvas for next time
clear(gctx);
// invalidate because we might need the selection border to disappear
invalidate();
}
function invalidate() {
canvasValid = false;
}
function getMouse(e) {
var element = canvas, offsetX = 0, offsetY = 0;
if (element.offsetParent) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
offsetX += stylePaddingLeft;
offsetY += stylePaddingTop;
offsetX += styleBorderLeft;
offsetY += styleBorderTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY
}
$("#btn-bold").click(function () {
for (var i = 0; i < textObjects.length() ; i++) {
if ((textObjects[i].x == mySel.x) && (textObjects[i].y == mySel.y)) {
if (textObjects[i].fontWeight == "normal") {
textObjects[i].fontWeight = "bold";
}
if (textObjects[i].fontWeight == "bold") {
textObjects[i].fontWeight = "normal";
}
}
}
});
HTML
<div id="top-level">
<div class="row" id="content-header">
<h1 style="text-align:center">Edit Photo's EditorView.cshtml</h1>
</div>
<div class="row" id="content-middle">
<div id="designer-canvas" class="col-md-8">
#{ Html.RenderPartial("ClientPage"); }
</div>
<div id="content-builder" class="col-md-4">
<row>
<div id=text-input-top-level class="col-md-12">
<h3><label>Text</label></h3>
<textarea id="text-inputarea" , placeholder="Text here."></textarea>
</div>
</row>
<hr />
<row>
<div id="text-size-check" class="col-md-12">
<h4>Font Size</h4>
<div id="font-size-slider">
<div id="font-size-slider-handle" class="ui-slider-handle"></div>
</div>
</div>
</row>
<hr />
<row>
<div id="text-weight-check" class="col-md-6">
<h4>Font Weight</h4>
<div id="text-weight-check-buttons">
<button id="btn-bold">B</button>
<button id="btn-italic">I</button>
</div>
</div>
<div id="text-position" class="col-md-6">
<h4>Text Position</h4>
<div id="text-position-buttons">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</div>
</div>
</row>
<hr />
<row>
</row>
</div>
</div>
</div>
ClientPage.cshtml
<canvas id="canvas"></canvas>
I'm trying to create 'snow' on the background of a single div. The code is below but you can see it here: http://www.getwiththebrand.com/makeabrew_copy/
I want to put the effect on the div with the red border only (number 4).
Can anyone tell me what I'm missing?
<!-- language: lang-js -->
var width = getWidth();
var height = getHeight();
var flakeCount = 50;
var gravity = 0.7;
var windSpeed = 20;
var flakes = [];
function getWidth() {
var x = 0;
if (self.innerHeight) {
x = self.innerWidth;
}
else if (document.documentElement && document.documentElement.clientHeight) {
x = document.documentElement.clientWidth;
}
else if (document.body) {
x = document.body.clientWidth;
}
return x;
}
function getHeight() {
var y = 0;
if (self.innerHeight) {
y = self.innerHeight;
}
else if (document.documentElement && document.documentElement.clientHeight) {
y = document.documentElement.clientHeight;
}
else if (document.body) {
y = document.body.clientHeight;
}
return y;
}
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var currentFlake = 0;
var snowglobe = document.getElementById("snowglobe");
while (currentFlake < flakeCount) {
var flake = document.createElement("div");
flake.className = 'flake';
flake.style.fontSize = getRandom(12, 24) + 'px';
flake.style.top = getRandom(0, height) + 'px';
flake.style.left = getRandom(0, width) + 'px';
flake.innerHTML = "•";
newFlake = snowglobe.appendChild(flake);
newFlake.speed = getRandom(1, 100);
flakes.push(newFlake);
currentFlake++;
}
function doAnimation() {
for (var i = 0; i < flakes.length; i++) {
newX = false;
newY = false;
// Calculate Y position
newY = parseFloat(flakes[i].style.top) + (flakes[i].speed / 100) * gravity;
if (newY > height) {
newY = 0 - parseInt(flakes[i].style.fontSize);
// If Y is at bottom, randomize X
newX = getRandom(0, width);
}
// Calculate X position if it hasn't been set randomly
if (!newX) newX = parseFloat(flakes[i].style.left) + Math.sin(newY / windSpeed);
if (newX < -20) newX = width + 20;
if (newX > width + 20) newX = -20;
// Set new position
flakes[i].style.top = newY + 'px';
flakes[i].style.left = newX + 'px';
}
}
setInterval(doAnimation, 10);
window.onresize = function(event) {
width = getWidth();
height = getHeight();
}
<!-- language: lang-css -->
#snowglobe .flake {
position: absolute;
width: 1px;
height: 1px;
color: rgba(255,255,255,0);
text-shadow: 0 0 3px rgba(255,255,255,1);
}
<!-- language: lang-html -->
<div class="ui-full-width">
<div class="container even" id="snowglobe">
<h3><span class="num">4</span>Add freshly boiled water to the pot</h3>
<p>Give it a stir and secure the lid. Wrap your pot in a tea-cosy if it's nippy outside!</p>
</div>
</div>
<!-- end snippet -->
<div class="ui-full-width">
<div class="container even" id="snowglobe">
<h3><span class="num">4</span>Add freshly boiled water to the pot</h3>
<p>Give it a stir and secure the lid. Wrap your pot in a tea-cosy if it's nippy outside!</p>
</div>
</div>
Your myjs.js has an extra character at the end of the file when it's loaded in my browser and it triggers a rightful
SCRIPT1014: Invalid character
myjs.js (116,2)
The script part:
window.onresize = function(event) {
width = getWidth();
height = getHeight();
}â // << here
Also, I don't know what browser you're using but try hitting F12, you'll get the console and you'll see javascript erros and other useful informations.
Edit: it's even worse, you have multiple characters at the end of your script:
window.onresize = function(event) {
width = getWidth();
height = getHeight();
}​ // ??
Did you mess around with some file encoding options?
thanks for looking. I commented out the code so that's what the extra characters were. I haven't done anything to the file encoding options.
I checked the console and there were some elements undefined. Looks like I missed a whole chunk:
var width = getWidth();
var height = getHeight();
var flakeCount = 50;
var gravity = 0.7;
var windSpeed = 20;
var flakes = [];
All good now!
I am using fabric.js to handle two canvases. I also set two canvases to compare two images in a same page.
like this:
<canvas id="firstImg" width="843" height="1200"></canvas>
<canvas id="secondImg" width="843" height="1200"></canvas>
I want to move a image when i drag the other image in the other canvas.
I mean when I drag a image to change the position in firstImg canvas, I also move the other image in secondImg canvas at same time.
Is it possible??
Were you looking for something like this?
I've made a simple function to draw an image on a canavs. When you drag the image you simply call the function for both canvas.
http://jsfiddle.net/Niddro/96rdnv3L/
var canvasOne = document.getElementById("canvasOne");
var ctxOne = canvasOne.getContext("2d");
var canvasTwo = document.getElementById("canvasTwo");
var ctxTwo = canvasTwo.getContext("2d");
var mouseX=0;
var mouseY=0;
var imageX=0;
var imageY=0;
var drag = false;
canvasOne.addEventListener("mousedown", function(){drag=true;}, false);
canvasOne.addEventListener("mouseup", function(){drag=false;}, false);
canvasOne.addEventListener("mousemove", moveImage, false);
var myImage = new Image();
myImage.src = "http://home.niddro.com/HTML5/flxprt/img/logo_orange_small.png";
function moveImage(event) {
if (drag) {
var x = new Number();
var y = new Number();
var canvas = document.getElementById("canvasOne");
if (event.x != undefined && event.y != undefined)
{
x = event.x;
y = event.y;
}
else // Firefox method to get the position
{
x = event.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
y = event.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
x -= canvas.offsetLeft;
y -= canvas.offsetTop;
var deltaX = mouseX-x;
var deltaY = mouseY-y;
drawImage(imageX-deltaX,imageY-deltaY,ctxOne,canvasOne,myImage);
drawImage(imageX-deltaX,imageY-deltaY,ctxTwo,canvasTwo,myImage);
}
}
drawImage(imageX,imageY,ctxOne,canvasOne,myImage);
drawImage(imageX,imageY,ctxTwo,canvasTwo,myImage);
function drawImage(x,y,ctx,canvas,img) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(img,x,y);
}
canvas {
border: 1px solid black;
}
<canvas id="canvasOne" width="500" height="300"></canvas><br />
<canvas id="canvasTwo" width="500" height="300"></canvas>
I'm trying to simulate the Matrix code rain with the canvas element and javascript. I am able to make one element drop at a time but not multiple. How do I drop multiple matrix rain drops. Here is my code:
<html>
<head>
<title>Matrix Code Rain</title>
<style>
*{margin:0; padding:0; }
body{background:black;}
</style>
</head>
<body>
<canvas id="c"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("c");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.background = "black";
var c = canvas.getContext("2d");
var code = ["<html>","<p>","<b>","<strong>","<head>","<body>","<a>","<i>","<div>","<form>","<ol>","<li>","<ul>","<pre>","<nav>","<footer>","<header>","<article>","<section>","<em>","<style>","<title>","<meta>","<br>","<table>"];
var rain = [ ];
var max = 10;
for(var i = 0; i < max; i++){
var drop = {};
drop.code = Math.round(Math.random() * code.length);
drop.x = Math.random() * canvas.width;
drop.y = 0;
drop.size = Math.random() * 40;
drop.speed = drop.size/4;
rain.push(drop);
}
var y = 0;
c.fillStyle="lime";
setTimeout(function(){
c.clearRect(0,0,canvas.width,canvas.height);
for(var i = 0; i < max; i++){
var drop = rain[i];
c.font = drop.size+"pt arial";
c.fillText(drop.code,drop.x,drop.y);
drop.y += drop.speed;
if(drop.y > canvas.height + drop.size)
drop.y = 0;
}
},1000/60);
</script>
</body>
</html>
Make a bunch of independent objects that all get their own word and position and speed.
Then print them all and advance them by their speed.
Here's a clean example for you:
http://jsfiddle.net/U5eFJ/
The important code:
var code = ["<html>", "<p>", "<b>", "<strong>", "<head>", "<body>", "<a>", "<i>", "<div>", "<form>", "<ol>", "<li>", "<ul>", "<pre>", "<nav>", "<footer>", "<header>", "<article>", "<section>", "<em>", "<style>", "<title>", "<meta>", "<br>", "<table>"];
// make 90 things to fall with a random code element and random starting location
var things = [];
var THINGCOUNT = 90;
for (var i = 0; i < THINGCOUNT; i++) {
var a = {};
//randomly pick one tag
a.code = code[Math.round(Math.random() * code.length)];
a.x = Math.random()*500; //random X
a.y = Math.random()*500 -500; // random Y that is above the screen
a.speed = Math.random()*10;
things.push(a);
}
setInterval(function() {
ctx.clearRect(0,0,500,500);
for (var i = 0; i < THINGCOUNT; i++) {
var a = things[i];
ctx.fillText(a.code, a.x, a.y);
a.y += a.speed; // fall downwards by the speed amount
if (a.y > 600) a.y = -50; // if off the screen at bottom put back to top
}
}, 90);
If you are running a windows computer you can make the java script open a .bat file that just says this.
`#echo off
mode 1000
#color a
:A
echo %random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%%random%
goto A'
This may not be what you want but I hope it helps =)
`