Background: I'm working on a library for creating "low resolution" display.
Now I wanted to test it with a simple demo - it should draw a radial gradient around cursor.
I think I got the math right and it is working, except when you move your mouse into the bottom left corner.
I tried printing the numbers, changing order and all, but can't find the cause.
Here is also a Fiddle: https://jsfiddle.net/to5qfk7o/
var size = 16; // number of pixels
var lo = new Lores('#board', size, size);
// DRAWING FUNCTION
setInterval(function () {
// Mouse coords
var m_x = lo.mouse.x;
var m_y = lo.mouse.y;
// print where is mouse - for debug
console.log(m_x + "," + m_y);
// for all pixels on screen
for (var x = 0; x < size; x++) {
for (var y = 0; y < size; y++) {
// mouse distance from this pixel
var distance = (Math.sqrt((m_x - x) * (m_x - x) + (m_y - y) * (m_y - y)));
// convert: 0..255, "size"..0
var color = 255 - Math.floor((255 / size) * distance);
// set color
if (color < 0) {
lo.set(y, x, 'black');
} else {
lo.set(x, y, 'rgb(' + color + ', 0, 0)');
}
}
}
}, 100);
// ---- LIBRARY CODE -----
function Lores(selector, width, height) {
this.boardElem = document.querySelector(selector);
this.boardElem.className += ' lores-screen';
this.grid = [];
this.mouse = {
inside: false,
x: 0,
y: 0 // position rounded to nearest board "pixel"
};
this.width = width;
this.height = height;
if (this.boardElem === null) {
console.error('No such element!');
return;
}
if (width <= 0 || height <= 0) {
console.error('Dimensions must be positive!');
return;
}
// Inject a style block for the sizes
var css = selector + ' > div {height:' + (100 / height) + '%}';
css += selector + ' > div > div {width:' + (100 / width) + '%}';
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.head.appendChild(style);
var frag = document.createDocumentFragment();
// Create the grid
for (var i = height; i > 0; i--) {
var rowElem = document.createElement('div');
rowElem.dataset.y = i;
var row = [];
for (var j = width; j > 0; j--) {
var cellElem = document.createElement('div');
cellElem.dataset.x = j;
rowElem.appendChild(cellElem);
row.push(cellElem);
}
frag.appendChild(rowElem);
this.grid.push(row);
}
this.boardElem.appendChild(frag);
console.log('yo');
var self = this;
// add mouse listener
document.addEventListener('mousemove', function (e) {
var rect = self.boardElem.getBoundingClientRect();
var x = (self.width * (e.clientX - rect.left)) / rect.width;
var y = (self.height * (e.clientY - rect.top)) / rect.height;
self.mouse.x = Math.floor(x);
self.mouse.y = Math.floor(y);
self.mouse.inside = (x >= 0 && x < self.width && y >= 0 && y < self.height);
}, false);
}
Lores.prototype.set = function (x, y, color) {
if (x < 0 || x >= this.width || y < 0 || y >= this.height) return;
this.grid[y][x].style.backgroundColor = color;
};
#board {
margin: 0 auto;
width: 128px;
height: 128px;
outline: 1px solid black;
}
#board > div:nth-child(odd) > div:nth-child(odd) {
background: #eee
}
#board > div:nth-child(even) > div:nth-child(even) {
background: #eee
}
.lores-screen {
display: block;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.lores-screen, .lores-screen * {
white-space: nowrap;
padding: 0;
}
.lores-screen * {
margin: 0
}
.lores-screen > div {
display: block;
}
.lores-screen > div > div {
display: inline-block;
vertical-align: top;
height: 100%;
}
<div id="board"></div>
It could be something trivial, I really don't know. Thanks!
The problem is a simple typo in your if statement. You have x and y mixed up in the set of your first branch. Having said that, we can eliminate the branch entirely. A simple Math.max(0, ...) will default it to black.
Change the following:
var color = 255 - Math.floor((255 / size) * distance);
// set color
if (color < 0) {
lo.set(y, x, 'black');
} else {
lo.set(x, y, 'rgb(' + color + ', 0, 0)');
}
to
var color = Math.max(0, 255-Math.floor((255 / size) * distance));
lo.set(x, y, 'rgb(' + color + ', 0, 0)');
jsfiddle
change
// set color
if (color < 0) {
lo.set(y, x, 'black');
} else {
lo.set(x, y, 'rgb(' + color + ', 0, 0)');
}
to
// set color
lo.set(x, y, 'rgb(' + Math.max(color, 0) + ', 0, 0)');
https://jsfiddle.net/hrvqa457/
Related
I started re-writing Windows!
The code below draws 10 canvas objects you can move around. I made them random sizes.
When you click on one it has thicker outline and can be dragged around.
When I added one line to change the initial top position of the canvases the move stopped working.
Its very odd, I only wanted to stack the windows in increasing 10px steps rather then them all starting at the same spot.
Why could this minor change stop the rest working?
var n = 0,
canv = [],
ct = []
var body = document.getElementsByTagName("body")[0];
var targ, wind = 10,
i, offx, offy = 0
for (n = 0; n < wind; n++) {
canv[n] = document.createElement('canvas');
canv[n].id = "C" + n;
canv[n].width = rnd(30 * n);
canv[n].height = rnd(30 * n);
//canv[n].style.top=10*n <- This line stops the drag effect working
canv[n].style.zIndex = n;
canv[n].style.position = "absolute";
canv[n].style.border = "2px solid";
body.appendChild(canv[n]);
targ=canv[0] // added now to stop errors before first click
ct[n] = canv[n].getContext("2d");
ct[n].fillText(n, canv[n].width / 2, canv[n].height / 2)
canv[n].addEventListener('mousedown', function(e) {
targ = e.currentTarget
if (targ.style.border == "2px solid") {
for (i = 0; i < wind; i++) {
canv[i].style.border = "2px solid"
}
targ.style.border = "5px solid";
offy = e.y - targ.style.top
} else {
targ.style.border = "2px solid"
}
});
canv[n].addEventListener('mousemove', function(e) {
if (targ.style.border == "5px solid") {
move(e.x, e.y)
}
});
}
function move(x, y) {
targ.style.top = y - offy
}
function rnd(m) {
return Math.floor(Math.random() * m)
}
You are using a global variable for when it is active. That is not set until a click happens so you get tons of errors.
When you are setting a position, it needs some sort of units.
Basic idea with the code cleaned up a bit.
const canv = [];
const ct = [];
const body = document.getElementsByTagName("body")[0];
let targ, wind = 10,
i, offx, offy = 0;
for (let n = 0; n < wind; n++) {
const canvas = document.createElement('canvas');
canv[n] = canvas;
canvas.id = "C" + n;
const width = rnd(30 * n);
const height = rnd(30 * n);
canvas.style.width = width + "px";
canvas.style.height = height + "px";
canvas.style.top = (10 * n) + "px";
canvas.style.left = (10 * n) + "px";
canvas.style.zIndex = n;
body.appendChild(canvas);
const ctx = canvas.getContext("2d");
ct[n] = ctx;
ctx.fillText(n, width / 2, height / 2)
canvas.addEventListener('mousedown', function(e) {
document.querySelectorAll("canvas.active").forEach(elem => {
elem.classList.remove("active");
});
targ = e.currentTarget;
targ.classList.add("active");
});
canvas.addEventListener('mousemove', function(e) {
if (targ && targ.classList.contains('active')) {
move(e.x, e.y)
}
});
}
function move(x, y) {
targ.style.top = y - offy + "px"
}
function rnd(m) {
return Math.floor(Math.random() * m)
}
canvas {
position: absolute;
min-width: 30px;
min-height: 30px;
border: 2px solid black;
z-index: 1;
}
canvas.active {
border: 5px solid black;
}
I am trying to do a Fibonacci Sphere with a canvas like the following code, but instead of the same point showing everywhere I want to show different images, possibly svgs like logos and other images. I've done some research in google like visiting codepen and other places but couldn't find anything that worked. I imagine it would be something like the one in this website here. Any idea on how to approach this?
var cant = 100;
var offset = 2 / cant;
var increment = Math.PI * (3 - Math.sqrt(5));
var canvas = document.getElementById("canvas");
var i;
var circle;
//---Build the elements
for(i = 0; i < cant; i++){
circle = document.createElement("div");
circle.className = "point";
circle.setAttribute("data-index", i);
canvas.appendChild(circle);
};
//---Apply transformations to points
function updatePoints(evt){
var x, y, z, r, a, scale, opacity, point, style;
var angle = (evt) ? (-evt.pageX / 4) * Math.PI / 180 : 0;
for(i = 0; i < cant; i++){
y = (i * offset - 1) + (offset / 2);
r = Math.sqrt(1 - Math.pow(y, 2));
a = ((i + 1) % cant) * increment + angle;
x = Math.cos(a) * r;
z = Math.sin(a) * r;
scale = Math.round(z * 20000) / 100;
opacity = (1 + z) / 1.5;
style = "translate3d(" + (125 + x * 100) + "px, " + (125 + y * 100) + "px, " + scale + "px)";
point = canvas.querySelectorAll("[data-index='" + i +"']");
point[0].style.WebkitTransform = style;
point[0].style.msTransform = style;
point[0].style.transform = style;
point[0].style.opacity = opacity;
}
}
//---Update the points at start
updatePoints();
//---Update the points on mouse move
document.addEventListener("mousemove", updatePoints);
body, html{
height: 100%;
position: relative;
}
body{
background-color: #232B2B;
margin: 0;
padding: 0;
}
#canvas{
height: 250vh;
margin: 0 0;
position: relative;
width: 250vh;
}
.point{
background: red;
border-radius: 50%;
height: 4px;
position: absolute;
transform-style: preserve-3d;
width: 4px;
}
<div id="canvas">
</div>
Any help would be most helpful.
You can continue using the createElement method.
I added this, to show a random image (from picsum) for each dot:
// Create a new img element
img = document.createElement('img');
// Add the src to each img element.
//Here using the iterator variable to
//change the id of the photo we are retrieving
img.src = 'https://picsum.photos/id/' + i +'/20/20'
// Append the img to the div
circle.appendChild(img);
And I made the circles a bit larger in the CSS (20px) so you can see it.
If you want specific images, you could create an array inside your JS, or pull from a folder on your server.
var cant = 100;
var offset = 2 / cant;
var increment = Math.PI * (3 - Math.sqrt(5));
var canvas = document.getElementById("canvas");
var i;
var circle;
//---Build the elements
for(i = 0; i < cant; i++){
circle = document.createElement("div");
img = document.createElement('img');
img.src = 'https://picsum.photos/id/' + i +'/20/20'
circle.appendChild(img);
circle.className = "point";
circle.setAttribute("data-index", i);
canvas.appendChild(circle);
};
//---Apply transformations to points
function updatePoints(evt){
var x, y, z, r, a, scale, opacity, point, style;
var angle = (evt) ? (-evt.pageX / 4) * Math.PI / 180 : 0;
for(i = 0; i < cant; i++){
y = (i * offset - 1) + (offset / 2);
r = Math.sqrt(1 - Math.pow(y, 2));
a = ((i + 1) % cant) * increment + angle;
x = Math.cos(a) * r;
z = Math.sin(a) * r;
scale = Math.round(z * 20000) / 100;
opacity = (1 + z) / 1.5;
style = "translate3d(" + (125 + x * 100) + "px, " + (125 + y * 100) + "px, " + scale + "px)";
point = canvas.querySelectorAll("[data-index='" + i +"']");
point[0].style.WebkitTransform = style;
point[0].style.msTransform = style;
point[0].style.transform = style;
point[0].style.opacity = opacity;
}
}
//---Update the points at start
updatePoints();
//---Update the points on mouse move
document.addEventListener("mousemove", updatePoints);
body, html{
height: 100%;
position: relative;
}
body{
background-color: #232B2B;
margin: 0;
padding: 0;
}
#canvas{
height: 250vh;
margin: 0 0;
position: relative;
width: 250vh;
}
.point{
background: red;
border-radius: 50%;
height: 20px;
position: absolute;
transform-style: preserve-3d;
width: 20px;
overflow: hidden;
}
<div id="canvas">
</div>
Clicking on one of the tiles triggers clickerbox().
The issue is that if the user clicks on a tile with b
no surrounding mines it's supposed to reveal them, and if any of those also have no mines it should do the same.
It seems to do some of this and then stop before revealing all the tiles it should. I was wondering if anyone knew why or how to fix this?
screenshot of the game board after a zero is clicked on
The first 5 clicks were made by the user then the rest where triggered by the function.
var width = 0;
var height = 0;
var bombs = 0;
var score = 0;
var boxs = 0;
let feild = new Array(2);
userfeild = new Array;
function selectdificulty() {
feild = new Array(2);
userfeild = new Array;
document.getElementById('board').innerHTML = '';
boxs = 0;
score = 0;
if (document.getElementById('dificulty').value == '4') {
var widthinput = document.createElement('input');
var heightinput = document.createElement('input');
var bombinput = document.createElement('input');
widthinput.placeholder = 'width';
heightinput.placeholder = 'height';
bombinput.placeholder = 'mines';
widthinput.id = 'width';
heightinput.id = 'height';
bombinput.id = 'bombs';
widthinput.setAttribute('type', 'text');
heightinput.setAttribute('type', 'text');
bombinput.setAttribute('type', 'text');
document.getElementById('board').appendChild(widthinput);
document.getElementById('board').appendChild(heightinput);
document.getElementById('board').appendChild(bombinput);
var entercustom = document.createElement('button')
entercustom.id = 'entercustom';
entercustom.innerHTML = 'enter custom values'
document.getElementById('board').appendChild(entercustom);
document.getElementById('entercustom').addEventListener('click', customsize);
} else {
if (document.getElementById('dificulty').value == '1') {
width = 9;
height = 9;
bombs = 10;
} else if (document.getElementById('dificulty').value == '2') {
width = 16;
height = 16;
bombs = 38;
} else if (document.getElementById('dificulty').value == '3') {
width = 32;
height = 16;
bombs = 99;
}
createuserboard(width, height, bombs);
}
}
function customsize() {
var width = document.getElementById('width').value;
var height = document.getElementById('height').value;
var bombs = document.getElementById('bombs').value;
if (!isNaN(width) && !isNaN(height) && !isNaN(bombs)) {
if (width * height <= 601) {
createuserboard(width, height, bombs);
}
}
}
function createuserboard(width, height, bombs) {
document.getElementById('board').innerHTML = '';
for (y = 0; y < height; y++) {
userfeild[y] = new Array;
var row = document.createElement('div');
row.classList = 'row';
row.id = 'row' + y;
document.getElementById('board').appendChild(row);
for (x = 0; x < width; x++) {
var box = document.createElement('button');
box.classList = 'box';
box.id = +y + ',' + x;
document.getElementById('row' + y).appendChild(box);
document.getElementById(y + ',' + x).onclick = clickedbox;
userfeild[y][x] = '/';
}
}
}
function clickedbox() {
var y = this.id.split(',')[0];
var x = this.id.split(',')[1];
if (boxs == 0) {
createmineboard(x, y)
}
autoclick(x, y);
}
function autoclick(x, y) {
userfeild[y][x] = feild[y][x];
boxs = boxs + 1;
document.getElementById(y + ',' + x).innerHTML = feild[y][x];
document.getElementById(y + ',' + x).classList = 'clickedbox';
console.log(userfeild[y][x] + ' | x:' + x + ' | y:' + y);
document.getElementById(y + ',' + x).onclick = '';
if (feild[y][x] == 9) {
//gameover();
} else if (feild[y][x] == 0) {
var check = [
[-1, 0, 1, -1, 1, -1, 0, 1],
[-1, -1, -1, 0, 0, 1, 1, 1]
];
for (i = 0; i < 8; i++) {
var newx = parseInt(x) + parseInt(check[0][i]);
var newy = parseInt(y) + parseInt(check[1][i]);
if (newx >= 0 && newx < width && newy >= 0 && newy < height) {
if (userfeild[newy][newx] == '/') {
autoclick(newx, newy);
}
}
}
}
}
function createmineboard(clickedx, clickedy) {
for (x = 0; x < height; x++) {
feild[x] = new Array;
for (y = 0; y < width; y++) {
feild[x][y] = 0;
}
}
for (bomb = 0; bomb < bombs;) {
var valid = false;
let bombx = 0;
let bomby = 0;
bombx = Math.floor(Math.random() * width);
bomby = Math.floor(Math.random() * height);
if (feild[bomby][bombx] !== 9 && !(bombx == clickedx && bomby == clickedy)) {
valid = true;
feild[bomby][bombx] = 9;
bomb++
}
}
function nearbombs(x, y, w, h, feild) {
var count = 0;
if (y !== 0) {
if (x !== 0) {
if (feild[y - 1][x - 1] == 9) {
count = count + 1
}
} //top left
if (feild[y - 1][x] == 9) {
count = count + 1
} //top
if (x !== w - 1) {
if (feild[y - 1][x + 1] == 9) {
count = count + 1
}
} //top right
}
if (x !== 0) {
if (feild[y][x - 1] == 9) {
count = count + 1
}
} //left
if (x !== w - 1) {
if (feild[y][x + 1] == 9) {
count = count + 1
}
} // right
if (y !== h - 1) {
if (x !== 0) {
if (feild[y + 1][x - 1] == 9) {
count = count + 1
}
} //bottom left
if (feild[y + 1][x] == 9) {
count = count + 1
} //bottom
if (x !== w - 1) {
if (feild[y + 1][x + 1] == 9) {
count = count + 1
}
} //bottom right
}
return count;
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (feild[y][x] == 0) {
feild[y][x] = nearbombs(x, y, width, height, feild);
}
}
}
console.log(feild);
}
.board {
display: flex;
flex-direction: column;
height: fit-content;
width: fit-content;
}
.row {
display: flex;
flex-direction: row;
height: fit-content;
width: fit-content;
background-color: aquamarine;
}
.box {
width: 30px;
height: 30px;
background-color: #C0C0C0;
border-radius: 0;
border: 0 solid;
box-shadow: inset 2px 2px #FFFFFF, inset -2px -2px #808080, inset 4px 4px #FFFFFF, inset -4px -4px #808080;
}
.clickedbox {
width: 30px;
height: 30px;
background-color: #C0C0C0;
border-radius: 0;
border: 0 solid;
box-shadow: inset 2px 2px #808080;
}
<select name="dificulty" id="dificulty" onchange="selectdificulty()">
<option value="1">begginer</option>
<option value="2">intermediate</option>
<option value="3">expert</option>
<option value="4">custom</option>
</select>
<script src="windows.js"></script>
<script src="minesweeper.js"></script>
<div class="board" id="board">
</div>
The mistake is hidden in for loop of autoclick function:
for (i = 0; i < 8; i++) { ... }
You have to use var keyword to create local iteration variable. Otherwise the global variable is created and reused by recursive calls.
for (var i = 0; i < 8; i++) { ... }
My favorite game btw.
I have the following canvas:
Codepen link
What I want: Equal margin on both sides of canvas without any horizontal scroll bars.
Problem: margin-right property does not to work. I have seen some solutions that solve this problem by specifying a fixed width, but I cannot have a fixed width in my case. I want my canvas to adjust its width height according to the size of the window.
The following Javascript takes care of that:
window.addEventListener('resize' , resizeCanvas , false);
function resizeCanvas(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight/1.2;
}
So is there a different solution?
For the overflow problem, if I put overflow-x: hidden inside the body then only the scrollbar disappears but the problem persists. The canvas still extends past the screen hence the right border of the canvas is No longer visible.
See here
Here is my code:
HTML
<body onload="start()">
<canvas id="myCanvas"></canvas>
</body>
CSS
body{
}
canvas{
border: 1px solid black;
border-radius: 5px;
background-color: #fff;
margin: auto 50px auto 50px; /* works for left margin but not for right */
}
Thanks!
Another thing:
I have not set width: 100% for the canvas because it distorts the content inside it.
As Chris is saying you need to set the width of the canvas lower than the full width of the page:
canvas.width = window.innerWidth - 100;
Note that you need to take the border-width of the canvas and in your codepen the body also has a margin of 8px into account as well:
canvas.width = window.innerWidth - 118;
CSS calc() method is what you need. Just subtract the margins from 100% and you get the desired result. See the demo below. CSS calc() reference
function start() {
var canvas = document.getElementById('myCanvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight / 1.2;
var ctx = canvas.getContext('2d');
function rand(min, max) {
return parseInt(Math.random() * (max - min + 1), 10) + min;
}
function get_random_color() {
var h = rand(1, 360);
var s = rand(30, 100);
var l = rand(30, 70);
return 'hsl(' + h + ',' + s + '%,' + l + '%)';
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var balls = [];
var ballCount = getRandomInt(2, 10);
//document.getElementById('ballCountInfo').innerHTML = ballCount;
//document.getElementById('box').innerHTML = ballCount;
var startpointX = 100;
var startpointY = 50;
for (var i = 0; i < ballCount; i++) {
var randValue = getRandomInt(20, 30);
balls.push({
x: startpointX,
y: startpointY,
vx: getRandomInt(3, 3) * direction(),
vy: getRandomInt(1, 1) * direction(),
radius: randValue,
mass: randValue,
color: get_random_color(),
draw: function() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
}
});
startpointX = startpointX + 50;
startpointY = startpointY + 40;
}
function direction() {
var chosenValue = Math.random() < 0.5 ? 1 : -1;
return chosenValue;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < ballCount; i++) {
balls[i].draw();
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
if ((balls[i].y + balls[i].vy + balls[i].radius) > canvas.height || (balls[i].y + balls[i].vy - balls[i].radius) < 0) {
balls[i].vy = -balls[i].vy;
}
if ((balls[i].x + balls[i].vx + balls[i].radius) > canvas.width || (balls[i].x + balls[i].vx - balls[i].radius) < 0) {
balls[i].vx = -balls[i].vx;
}
}
// onBoxTouched();
//collision check
for (var i = 0; i < ballCount; i++) {
for (var j = i + 1; j < ballCount; j++) {
var distance = Math.sqrt(
(balls[i].x - balls[j].x) * (balls[i].x - balls[j].x) +
(balls[i].y - balls[j].y) * (balls[i].y - balls[j].y)
);
if (distance < (balls[i].radius + balls[j].radius)) {
var ax = (balls[i].vx * (balls[i].mass - balls[j].mass) + (2 * balls[j].mass * balls[j].vx)) / (balls[i].mass + balls[j].mass);
var ay = (balls[i].vy * (balls[i].mass - balls[j].mass) + (2 * balls[j].mass * balls[j].vy)) / (balls[i].mass + balls[j].mass);
balls[j].vx = (balls[j].vx * (balls[j].mass - balls[i].mass) + (2 * balls[i].mass * balls[i].vx)) / (balls[i].mass + balls[j].mass);
balls[j].vy = (balls[j].vy * (balls[j].mass - balls[i].mass) + (2 * balls[i].mass * balls[i].vy)) / (balls[i].mass + balls[j].mass);
balls[i].vx = ax;
balls[i].vy = ay;
}
}
}
raf = window.requestAnimationFrame(draw);
}
function onBoxTouched() {
for (var i = 0; i < ballCount; i++) {
if (balls[i].x + balls[i].radius > 600 && balls[i].x + balls[i].radius < 750 &&
balls[i].y + balls[i].radius > 200 && balls[i].y + balls[i].radius < 350) {
//var ele = document.getElementById("box");
ele.style.backgroundColor = balls[i].color;
balls.splice(i, 1);
ballCount = ballCount - 1;
if (ballCount == 0) {
ele.style.fontSize = "x-large";
ele.innerHTML = "Over";
} else {
ele.innerHTML = ballCount;
}
//document.getElementById('ballCountInfo').innerHTML=" "+ballCount;
}
}
}
window.requestAnimationFrame(draw);
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight / 1.2;
}
}
* {}
html,
body {}
canvas {
border: 1px solid black;
border-radius: 5px;
background-color: #fff;
width: calc(100% - 40px);
/*substract the total margin from 100% and will automoatically adjuts accordint to your need*/
margin: auto 20px auto 20px;
/* works for left margin but not for right */
}
#box {
width: 150px;
height: 150px;
background-color: plum;
border-radius: 5px;
position: absolute;
top: 200px;
left: 600px;
font-size: 72px;
font-weight: bold;
color: white;
line-height: 150px;
text-align: center;
}
#info {
float: left;
font-size: 24px;
color: #6D8390;
margin-top: 20px;
}
<body onload="start()">
<canvas id="myCanvas"></canvas>
</body>
Hope it helps :)
instead of messing around with margins, just change the width of your canvas and center it.
CSS
canvas {
border: 1px solid black;
border-radius: 5px;
background-color: #fff;
width: 90%!important;
}
HTML
<body onload="start()">
<center>
<canvas id="myCanvas"></canvas>
</center>
</body>
https://codepen.io/anon/pen/GEmLPL
I'm developing an app to help autistic children prepare to learn to write. It's very straight forward. They just need to draw a line straight down. I have it working very similar to "connect the dots" where they start at a green light, progress to yellow and then to red. However, on my webpage using a mouse everything works great because the "dots" are "touched" using the mouseover, like so:
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="jquery.jplayer.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
var dots = [13, 15, 13, 25, 13, 55, -1, -1,
45, 15, 45, 40, -1, -1,
70, 15, 70, 40, -1, -1,
80, 15, 80, 40, 80, 60, -1, -1];
function contains(arr, value) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == value) {
return true;
}
}
return false;
}
function getRandomPoints(totalPoints) {
var indexes = new Array();
for (var i = 0; i < totalPoints; i++) {
var done = false;
while (!done) {
var index = Math.floor(Math.random() * dots.length);
if (index % 2 != 0) {
index++;
if (index > dots.length) {
continue;
}
}
if (!contains(indexes, index)) {
indexes.push(index);
done = true;
}
}
}
return indexes.sort(function(a, b) {
return a - b;
});
}
function displayGrid(ctx) {
var gridSize = 20, width = 900;
for (var ypos = 0; ypos < width; ypos += gridSize) {
ctx.moveTo(0, ypos);
ctx.lineTo(width, ypos);
}
for (var xpos = 0; xpos < width; xpos += gridSize) {
ctx.moveTo(xpos, 0);
ctx.lineTo(xpos, width);
}
ctx.strokeStyle = "#eee";
ctx.lineWidth = .7;
ctx.stroke();
}
function addPoint(index, x1, y1) {
for (var i = 0; i < points.length; i++) {
var x2 = points[i].x, y2 = points[i].y;
var d1 = Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2));
var d2 = radius * 2 + 2;
if (d2 > d1) {
return false;
}
}
points.push({ 'x': x1, 'y': y1, 'index': index });
return true;
}
//Initialization....
var $graph = $('#graph'), gpos = $graph.position();
var $timer = $('#timer');
var points = new Array();
var ctx = $graph.get(0).getContext("2d");
//Parameters...
var indexes = getRandomPoints(7), ratio = 3, hops = 0, point = 0, maxTotalHops = 60, radius = 12;
var lineWidth = 11.5;
var xDisplacement = 0, yDisplacement = 0;
var borderColor = 'rgb(0,102,204)';
//Display the character's fixed lines...
ctx.beginPath();
ctx.translate(xDisplacement, yDisplacement);
ctx.lineWidth = lineWidth;
for (var i = 0; i < dots.length; i += 2) {
var newLine = dots[i] == -1;
if (newLine) {
i += 2;
}
var x = ratio * dots[i], y = ratio * dots[i + 1];
if (hops == 0 && contains(indexes, i)) {
hops++;
ctx.moveTo(x, y);
continue;
}
if (newLine || i == 0) {
ctx.moveTo(x, y);
}
else {
if (hops == 0) {
ctx.lineTo(x, y);
}
else {
ctx.strokeStyle = borderColor;
ctx.stroke();
ctx.beginPath();
if (addPoint(i, x, y)) {
var cx = gpos.left + xDisplacement - radius + 1 + x;
var cy = gpos.top + yDisplacement - radius + 1 + y;
$('<span></span>')
.addClass('circle')
.html(++point)
.data('pos', { 'x': cx, 'y': cy })
.css({ 'top': 0, 'left': 0 })
.insertAfter($graph);
}
}
}
if (hops > maxTotalHops) {
hops = 0;
}
else if (hops > 0) {
hops++;
}
}
ctx.strokeStyle = borderColor;
ctx.stroke();
//Create and initialize hotspots...
var passed = 0;
$('.circle').each(function() {
var pos = $(this).data('pos');
$(this).animate({
left: pos.x,
top: pos.y
}, 700);
}).mousemove(function() { // <====================== this part
var index = parseInt($(this).text());
if (passed != index - 1) {
return;
}
$(this).css({
'color': '#c00',
'font-weight': 'bold'
}).animate({
left: 0,
top: 0,
opacity: 0
}, 1000);
ctx.beginPath();
var start, end, done = passed + 1 == points.length;
if (done) /*The entire hotspots are detected...*/{
start = 0;
end = dots.length - 2;
clearInterval(tid);
$timer.html('Well done, it took ' + $timer.html() + ' seconds!').animate({
left: gpos.left + $graph.width() - $timer.width() - 20
}, 1000);
}
else {
start = passed == 0 ? points[passed].index - 4 : points[passed - 1].index;
end = points[passed].index;
}
for (var i = start; i <= end; i += 2) {
var newLine = dots[i] == -1;
if (newLine) {
i += 2;
}
var x = ratio * dots[i], y = ratio * dots[i + 1];
if (newLine || i == start) {
ctx.moveTo(x, y);
}
else {
ctx.lineTo(x, y);
}
}
ctx.lineWidth = lineWidth;
ctx.strokeStyle = borderColor;
ctx.stroke();
if (done) {
$('.filled').css({
left: gpos.left + xDisplacement + 10,
top: gpos.top + yDisplacement + 150
}).fadeIn('slow');
}
passed++;
});
//Initialize timer...
$timer.css({
top: gpos.top + 10,
left: gpos.left + 10
});
var timer = 0, tid = setInterval(function() {
timer += 30 / 1000;
$timer.html(timer.toFixed(2));
}, 30);
});
</script>
<style type="text/css">
.circle {
background: url('start.png');
width: 24px;
height: 24px;
text-align: center;
font-size: .8em;
line-height: 24px;
display: block;
position: absolute;
cursor: pointer;
color: #333;
z-index: 100;
}
.filled {
background: url('train.gif');
position: absolute;
width: 172px;
height: 251px;
display: none;
}
#timer {
position: absolute;
font-family: Arial;
font-weight: bold;
font-size: 1em;
background: #c00;
color: #fff;
padding: 5px;
text-align: center;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
font-variant: small-caps;
}
#graph {
background: url('vlinesbackground.jpg');
left: 5px;
top: 20px;
position: relative;
border: 1px dotted #ddd;
}
</style>
But I'm trying to replace the mousemove so the app can be used on the iphone. I've worked out everything else but triggering the "dots" and although I've looked at all the touchstart/touchmove info I can google, nothing appears to be working. Suggestions? Thanks!