I'm currently trying to get a similar touch/stylus behaviour to Squid (the notetaking app). I have used the PointerEvent API and it all works, except for one annoying issue:
After I put down the stylus or the finger, it draws a stroke for the next ~0.3 seconds, but after that, no more pointermove events are fired as long as the pointer is down.
here's my code:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draw</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<canvas id="canvas" width="500px" height="500px" style=" position: absolute;border: 2px solid red;"></canvas>
<script src="index.js"></script>
</body>
</html>
index.js
var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "white"
var pos = {}
canvas.addEventListener("pointerdown", function (e) {
pos.x = e.pageX;
pos.y = e.pageY;
});
canvas.addEventListener("pointermove", function (e) {
console.log(e.pressure)
switch (e.pointerType) {
case "pen":
ctx.beginPath();
ctx.moveTo(pos.x, pos.y);
ctx.lineTo(e.pageX, e.pageY);
ctx.stroke();
pos.x = e.pageX;
pos.y = e.pageY;
break;
case "touch":
ctx.fillRect(e.pageX - 10, e.pageY - 10, 20, 20);
break;
}
});
index.css is just a css reset
I'm really confused over this and can't seem to find anyone else who had this problem. Any help would be appreciated!
Just add touch-action: none; to your canvas's style attribute.
After ~0.3 seconds starts touch events as page scrolling.
Related
It's my first question here. I just learn canvas in JavaScript and I found a problem while adding the speed. I want to stop the rectangle if its x exceeds the width of the canvas. I am just a beginner, so please help me.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#canvas{
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">Your browser doesn't support canvas</canvas>
<script>
var canvas = document.getElementById('canvas');
var cnxt = canvas.getContext('2d');
x = 0;
y = 50;
var t;
function draw(){
cnxt.clearRect(0,0,400,400);
cnxt.beginPath();
cnxt.rect(x,y,25,25);
cnxt.fillStyle = 'red';
cnxt.fill();
var timePassed = (performance.now()-t)/1000;
var fps = Math.round(1/ timePassed);
let speed = 100;
cnxt.font = '25px Arial';
cnxt.fillStyle = 'black';
cnxt.fillText("FPS: " + fps, 20,30);
t = performance.now();
x += (speed * timePassed);
if (x >= 400 - 25){
speed = 0;
}
window.requestAnimationFrame(draw);
}
draw();
</script>
</body>
</html>
I have a very simple HTML/Js code that is supposed to draw a simple circle on a canvas.
const canvas=
document.querySelector('#canvas1');
const ctx= canvas.getContext('2d');
ctx.canvas.width= window.innerWidth;
ctx.canvas.height= window.innerHeight;
class Particule{
constructor(x, y, dirX, dirY, taille, coul){
this.x= x;
this.y= y;
this.dirX= dirX;
this.dirY= dirY;
this.taille= taille;
this.coul= coul;
}
dessine(){
ctx.beginPath();
ctx.arc(this.x, this.y, this.taille, 0,
Math.pi * 2, false);
ctx.fillStyle= this.coul;
ctx.fill();
}
}
const ob= new Particule(10, 10, 50, 50, 100, "white");
ob.dessine();
console.log(ob);
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
#canvas1{
position: absolute;
width: 100%;
height: 100%;
background: #333;
}
<!DOCTYPE html>
<html>
<head>
<title>Particles</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<canvas id="canvas1">
</canvas>
<script type="text/javascript" src='script.js'></script>
</body>
</html>
The code is supposed to output a white circle on the top left corner of the screen but when I launch it, just the dark grey background appears even though there is no error logs on the console.
On Firefox, the is a warning saying
Use of mozImageSmoothingEnabled is deprecated. Please use the
unprefixed imageSmoothingEnabled property instead.
and I think it 'may' be the reason why things are not working.
The problem is I DON'T have mozImageSmoothingEnabled or ImageSmoothingEnabled anywhere in my code. I didn't even use it in the first place so how would I be able to replace it?
I am using the latest version of Firefox and I couldn't find any help about this anywhere.
If anyone can indicate me how could I fix this, it would be of great help.
Thanks in advance.
You should use Math.PI instead of Math.pi bro ^_^
Advices
Use a modern IDE/Code editor that will be help you with this little errors.
Use debugger to what values use computer. If you create breakpoint at the start and see step by step all your values in code you see that problem is in Math.pi
I have been trying to develop a drawing application. When I try to plot a point for freehand drawing, the point appears a good 100 or so pixels away from the actual position of the mouse pointer. Is there any way I can get the exact position of the mouse? You can see and run the code below.
const canvasEle = document.getElementById('drawContainer');
const context = canvasEle.getContext('2d');
function setMousePosition (e) {
var x = e.clientX;
var y = e.clientY;
console.log("x coord " + x + " y coord " + y);
changePixelColor(x, y)
}
function changePixelColor (x, y) {
context.fillRect(x,y,1,1);
}
canvasEle.addEventListener("mousemove", setMousePosition)
canvas {
border: 1px solid black;
width: 500px;
height: 500px;
position: absolute;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draw</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="drawContainer"></canvas>
</body>
<script src="app.js"></script>
</html>
Try like this:
const canvasEle = document.getElementById('drawContainer');
const context = canvasEle.getContext('2d');
const cr = canvasEle.getBoundingClientRect();
function setMousePosition (e) {
var x = e.clientX - cr.x;
var y = e.clientY - cr.y;
console.log("x coord " + x + " y coord " + y);
changePixelColor(x, y)
}
function changePixelColor (x, y) {
context.fillRect(x,y,1,1);
}
canvasEle.width = 500;
canvasEle.height = 500;
canvasEle.addEventListener("mousemove", setMousePosition)
canvas {
border: 1px solid black;
width: 500px;
height: 500px;
position: absolute;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draw</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="drawContainer"></canvas>
</body>
<script src="app.js"></script>
</html>
Two additions to resolve this:
offsetting the x and y values in setMousePosition, so that they become relative to the canvas position, rather than to the page.
setting the width and height of the canvas element in either JavaScript or the HTML attributes.
Try removing height and width from CSS and use the canvas' width and height attributes instead. Another tip to center the mouse on the painted rectangle is to subtract half the size of the rectangle, e.g. context.fillRect(x-0.5,y-0.5,1,1). In your case it's hard to actually see that the dot isn't centered so try with context.fillRect(x-25,y-25,50,50) and you will see a difference compared to context.fillRect(x-25,y,50,50)
const canvasEle = document.getElementById('drawContainer');
const context = canvasEle.getContext('2d');
function setMousePosition (e) {
var x = e.clientX;
var y = e.clientY;
//console.log("x coord " + x + " y coord " + y);
changePixelColor(x, y)
}
function changePixelColor (x, y) {
context.fillRect(x-0.5,y-0.5,1,1);
//context.fillRect(x,y,50,50); compare these to see the difference
//context.fillRect(x-25,y-25,50,50);
}
canvasEle.addEventListener("mousemove", setMousePosition)
canvas {
border: 1px solid black;
position: absolute;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draw</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas width="500" height="500" id="drawContainer"></canvas>
</body>
<script src="app.js"></script>
</html>
We have a situation where we have a number of (animated) .gif files. We can change the underlying .gif, but that resets the new one to start. What we would want is to have the playback continue with the new .gif (all our .gif's have the same layout/number of frames/etc.)
The first in this process would probably be something like:
Is it possible to get currently shown frame of a .gif ?
Not gif. But you can do for html. the basic code be found on.
https://odetocode.com/blogs/scott/archive/2013/01/04/capturing-html-5-video-to-an-image.aspx
converting GIF to mp4
https://www.smashingmagazine.com/2018/11/gif-to-video/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<video id="video" controls="controls">
<source src="element_stream.mp4" crossorigin="anonymous" />
</video>
<button id="capture">Capture</button>
<div id="output" crossorigin></div>
</div>
<script>
(function () {
"use strict";
var video, output;
var scale = 0.25;
output = document.querySelector("#output");
video = document.querySelector("#video");
document.querySelector("#capture").addEventListener('click', function () {
var canvas = document.createElement("canvas");
canvas.width = video.videoWidth * scale;
canvas.height = video.videoHeight * scale;
canvas.getContext('2d')
.drawImage(video, 0, 0, canvas.width, canvas.height);
var img = document.createElement("img");
img.src = canvas.toDataURL();
output.prepend(img);
});
}());
</script>
</body>
</html>
I need to program a html-based monitoring surface.
For the surface I need to code circles which move from x to y and only if number xy is greater than xy.
Hard to explain but actually similar like they have it on
https://www.solarweb.com
click "click to try the preview now" on the top, than click "view demo" and choose the first system "Fronius AT Sattledt Hybrid 2"
and see the animation above on the left side.
I´ve still been able to get a circle running from the beginning of a div to the end. but only 1 circle! is it possible to have more circles in a row doing the same?
Maybe anyone can help me :)
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Moving Bullet</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style>
#energieFluss {
width: 900px;
height: 500px;
border: 5px black solid;
overflow: hidden;
}
#bullet {
position: relative;
left: 50px;
top: 25px;
}
</style>
<body>
<div id="energieFluss" width="900px" height="500px" color="red">
<img id="bullet" src="ball-blau.png" height ="25" width= "25">
</div>
<script>
var Bullet = document.querySelector ("#bullet");
var currentPos = 0;
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function moveBullet () {
currentPos += 8;
Bullet.style.left = currentPos + "px";
if (Math.abs(currentPos) >= 900) {
currentPos = -50;
}
requestAnimationFrame(moveBullet);
}
moveBullet ();
</script>
</body>
I think what you'll want to do here is create your image elements on the fly and then animate them. You could also do other fancy things like render on a canvas or use a JavaScript rendering library to do it more efficiently.
To create the elements on the fly, do something like this:
var balls = [];
// Run this in a loop to add each ball to the balls array.
var img = document.createElement("img");
img.src = "ball-blau.png";
img.height = 25;
img.width = 25;
document.getElementById("energieFluss").appendChild(img);
balls.push(img)
Post thought:
You could just statically define your image elements and animate multiple elements. If you already know how to animate one element, then you can apply that same knowledge to multiple.