Javascript Easing no working in Firefox - javascript

The below HTML and Javascript has an easing function applied to a background. It works fine in Chrome, Safari, and even IE, but not firefox?
anyone out there know why it wont work in FF?
var element = "ele";
var ease_against = true;
window.onload = function() {
var target = {
x: 0,
y: 0
};
var position = {
x: target.x,
y: target.y
},
ease = 0.2;
document.getElementById(element).addEventListener("mousemove", function(event) {
target.x = event.clientX / 5;
target.y = event.clientY / 5;
});
update();
function update() {
var vx = ease_against ? (((target.x - target.x - target.x) - position.x) * ease) : ((target.x - position.x) * ease);
var vy = ease_against ? (((target.y - target.y - target.y) - position.y) * ease) : ((target.y - position.y) * ease);
position.x += vx;
position.y += vy;
document.getElementById(element).style.backgroundPositionY = position.y + "px";
document.getElementById(element).style.backgroundPositionX = position.x + "px";
requestAnimationFrame(update);
}
};
html,
body {
margin: 0;
width: 100%;
height: 100%;
padding: 0;
}
#ele {
background: url('hex.jpg') repeat;
width: 400px;
height: 400px;
margin-left: auto;
margin-right: auto;
border-top: 1px solid black;
border-bottom: 1px solid black;
border-radius: 50%;
overflow: hidden;
}
<div id="ele">
</div>

It's not the easing that causes your problem.
Firefox doesn't support backgroundPositionX, but it does support background position
For example you can do:
myElement.style.backgroundPosition = position.x + "px "+position.y + "px";

Related

Not able to get the input text box editable inside animated javascript

I have added the code snippet over here. I was trying to do some random exercise. Can someone look why my textbox is not editable. There is falling leaf animation over here. Along with I have added one textbox on top of it. But currently I am not able to add any text to the textbox.
I am just adding more text in order to overcome the error message that the post is mostly having code and not much explanation.
var LeafScene = function(el) {
this.viewport = el;
this.world = document.createElement('div');
this.leaves = [];
this.options = {
numLeaves: 20,
wind: {
magnitude: 1.2,
maxSpeed: 12,
duration: 300,
start: 0,
speed: 0
},
};
this.width = this.viewport.offsetWidth;
this.height = this.viewport.offsetHeight;
// animation helper
this.timer = 0;
this._resetLeaf = function(leaf) {
// place leaf towards the top left
leaf.x = this.width * 2 - Math.random()*this.width*1.75;
leaf.y = -10;
leaf.z = Math.random()*200;
if (leaf.x > this.width) {
leaf.x = this.width + 10;
leaf.y = Math.random()*this.height/2;
}
// at the start, the leaf can be anywhere
if (this.timer == 0) {
leaf.y = Math.random()*this.height;
}
// Choose axis of rotation.
// If axis is not X, chose a random static x-rotation for greater variability
leaf.rotation.speed = Math.random()*10;
var randomAxis = Math.random();
if (randomAxis > 0.5) {
leaf.rotation.axis = 'X';
} else if (randomAxis > 0.25) {
leaf.rotation.axis = 'Y';
leaf.rotation.x = Math.random()*180 + 90;
} else {
leaf.rotation.axis = 'Z';
leaf.rotation.x = Math.random()*360 - 180;
// looks weird if the rotation is too fast around this axis
leaf.rotation.speed = Math.random()*3;
}
// random speed
leaf.xSpeedVariation = Math.random() * 0.8 - 0.4;
leaf.ySpeed = Math.random() + 1.5;
return leaf;
}
this._updateLeaf = function(leaf) {
var leafWindSpeed = this.options.wind.speed(this.timer - this.options.wind.start, leaf.y);
var xSpeed = leafWindSpeed + leaf.xSpeedVariation;
leaf.x -= xSpeed;
leaf.y += leaf.ySpeed;
leaf.rotation.value += leaf.rotation.speed;
var t = 'translateX( ' + leaf.x + 'px ) translateY( ' + leaf.y + 'px ) translateZ( ' + leaf.z + 'px ) rotate' + leaf.rotation.axis + '( ' + leaf.rotation.value + 'deg )';
if (leaf.rotation.axis !== 'X') {
t += ' rotateX(' + leaf.rotation.x + 'deg)';
}
leaf.el.style.webkitTransform = t;
leaf.el.style.MozTransform = t;
leaf.el.style.oTransform = t;
leaf.el.style.transform = t;
// reset if out of view
if (leaf.x < -10 || leaf.y > this.height + 10) {
this._resetLeaf(leaf);
}
}
this._updateWind = function() {
// wind follows a sine curve: asin(b*time + c) + a
// where a = wind magnitude as a function of leaf position, b = wind.duration, c = offset
// wind duration should be related to wind magnitude, e.g. higher windspeed means longer gust duration
if (this.timer === 0 || this.timer > (this.options.wind.start + this.options.wind.duration)) {
this.options.wind.magnitude = Math.random() * this.options.wind.maxSpeed;
this.options.wind.duration = this.options.wind.magnitude * 50 + (Math.random() * 20 - 10);
this.options.wind.start = this.timer;
var screenHeight = this.height;
this.options.wind.speed = function(t, y) {
// should go from full wind speed at the top, to 1/2 speed at the bottom, using leaf Y
var a = this.magnitude/2 * (screenHeight - 2*y/3)/screenHeight;
return a * Math.sin(2*Math.PI/this.duration * t + (3 * Math.PI/2)) + a;
}
}
}
}
LeafScene.prototype.init = function() {
for (var i = 0; i < this.options.numLeaves; i++) {
var leaf = {
el: document.createElement('div'),
x: 0,
y: 0,
z: 0,
rotation: {
axis: 'X',
value: 0,
speed: 0,
x: 0
},
xSpeedVariation: 0,
ySpeed: 0,
path: {
type: 1,
start: 0,
},
image: 1
};
this._resetLeaf(leaf);
this.leaves.push(leaf);
this.world.appendChild(leaf.el);
}
this.world.className = 'leaf-scene';
this.viewport.appendChild(this.world);
// set perspective
this.world.style.webkitPerspective = "400px";
this.world.style.MozPerspective = "400px";
this.world.style.oPerspective = "400px";
this.world.style.perspective = "400px";
// reset window height/width on resize
var self = this;
window.onresize = function(event) {
self.width = self.viewport.offsetWidth;
self.height = self.viewport.offsetHeight;
};
}
LeafScene.prototype.render = function() {
this._updateWind();
for (var i = 0; i < this.leaves.length; i++) {
this._updateLeaf(this.leaves[i]);
}
this.timer++;
requestAnimationFrame(this.render.bind(this));
}
// start up leaf scene
var leafContainer = document.querySelector('.falling-leaves'),
leaves = new LeafScene(leafContainer);
leaves.init();
leaves.render();
body, html {
height: 100%;
}
form {
width: 600px;
margin: 0px auto;
padding: 15px;
}
input[type=text] {
display: block;
padding: 10px;
box-sizing: border-box;
font-size: x-large;
margin-top: 25%;
}
input[type=text] {
width: 100%;
margin-bottom: 15px;
}
.falling-leaves {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 100%;
max-width: 880px;
max-height: 880px; /* image is only 880x880 */
transform: translate(-50%, 0);
border: 20px solid #fff;
border-radius: 50px;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/125707/sidebar-bg.png) no-repeat center center;
background-size: cover;
overflow: hidden;
}
.leaf-scene {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
transform-style: preserve-3d;
}
.leaf-scene div {
position: absolute;
top: 0;
left: 0;
width: 20px;
height: 20px;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/125707/leaf.svg) no-repeat;
background-size: 100%;
transform-style: preserve-3d;
backface-visibility: visible;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="style/style.css">
</head>
<body>
<div class="falling-leaves">
<form id="frmContact">
<input type="text" id="txtName" name="txtName" placeholder="Text goes here">
</form>
</div>
<script src="script/script.js"></script>
</body>
</html>

How to Draw on rotated canvas using mouse?

I want to draw on img its work fine but when i rotate the image its drawing axis is total change and it not draw on the right area
https://codepen.io/ali-shahzil/project/editor/AddPLW
var canvas;
var ctx;
var SCALE_MIN = 1,
SCALE_MAX = 25;
var currScale = 0; // def pic width=600px, 100px=1scale unit
var xscale = 1.0;
var scaleFactor = 1.00;
var painting = false,
mark = true,
lastX = 0,
lastY = 0,
lineThickness = 0.3,
width = 600,
height = 600;
var img = new Image();
img.src = 'img.JPG';
img.onload = function() {
canvas = document.getElementById("canvas1"),
ctx = canvas.getContext("2d");
canvas.height = height;
canvas.width = width;
ctx.drawImage(img, 5, 40, canvas.width, canvas.height);
canvas = document.getElementById("canvas2"),
ctx = canvas.getContext("2d");
canvas.height = height;
canvas.width = width;
ctx.drawImage(img, 5, 40, canvas.width, canvas.height);
canvas = ctx = ''; //reset
}
function doMarking() {
var checkBox = document.getElementById("mark");
if (checkBox.checked == true) {
mark = true;
if (canvas != null)
canvas.style.cursor = "pointer";
//currImgId = '';
} else {
mark = false;
if (canvas != null);
canvas.style.cursor = "";
}
lastX = 0,
lastY = 0,
painting = false;
}
function mouseDown(e) {
if (!mark)
return;
painting = true;
ctx.fillStyle = "#ffffff";
lastX = e.pageX - (e.target).offsetLeft;
lastY = e.pageY - (e.target).offsetTop;
//Calculating the scale how much it increase
var rect = canvas.getBoundingClientRect(); // abs. size of element
scaleX = canvas.width / rect.width; // relationship bitmap vs. element for X
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
lastX = lastX * scaleX;
lastY = lastY * scaleY;
//console.log('Before lasX=' + lastX + ' lastY=' + lastY+',currScale='+currScale);
//lastX=transformSimple(lastX);
// lastY=transformSimple(lastY);
//console.log('After lasX=' + lastX + ' lastY=' + lastY+', currScale='+currScale);
//console.log('offleft=' + (e.target).offsetLeft + ', offsetTop=' + (e.target).offsetTop);
// console.log('e=' + e);
}
/*
canvas1.onmousedown=function (e) {
console.log('mousedown2 id=' + e);
if (!mark)
return;
painting = true;
ctx.fillStyle = "#ffffff";
lastX = e.pageX - this.offsetLeft;
lastY = e.pageY - this.offsetTop;
console.log('lasX=' + lastX + ' lastY=' + lastY);
}
*/
function mouseUp(e) {
if (!mark)
return;
painting = false;
}
function mouseMove(e) {
if (!mark)
return;
if (painting) {
mouseX = e.pageX - (e.target).offsetLeft;
mouseY = e.pageY - (e.target).offsetTop;
//Calculating the scale how much it increase
var rect = canvas.getBoundingClientRect(); // abs. size of element
scaleX = canvas.width / rect.width; // relationship bitmap vs. element for X
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
mouseX = mouseX * scaleX;
mouseY = mouseY * scaleY;
// mouseX=transformSimple(mouseX);
// mouseY=transformSimple(mouseY);
//console.log('mx=' + mouseX + ', my=' + mouseY);
// find all points between
var x1 = mouseX,
x2 = lastX,
y1 = mouseY,
y2 = lastY;
var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
if (steep) {
var x = x1;
x1 = y1;
y1 = x;
var y = y2;
y2 = x2;
x2 = y;
}
if (x1 > x2) {
var x = x1;
x1 = x2;
x2 = x;
var y = y1;
y1 = y2;
y2 = y;
}
var dx = x2 - x1,
dy = Math.abs(y2 - y1),
error = 0,
de = dy / dx,
yStep = -1,
y = y1;
if (y1 < y2) {
yStep = 1;
}
lineThickness = 5 - Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) / 10;
if (lineThickness < 1) {
lineThickness = 1;
}
for (var x = x1; x < x2; x++) {
if (steep) {
// translate(y,x);
ctx.fillRect(y, x, lineThickness, lineThickness);
//ctx.fillRect(transformSimple(y), transformSimple(x), lineThickness, lineThickness);
} else {
ctx.fillRect(x, y, lineThickness, lineThickness);
}
error += de;
if (error >= 0.5) {
y += yStep;
error -= 1.0;
}
// console.log('x=' + x + ', y=' + y );
}
lastX = mouseX;
lastY = mouseY;
}
}
/*
canvas.addEventListener('click', function (event) {
if (mark)
return;
//get the img of convas
});*/
//-------------- img zooms
function zoomin_canvas() {
if (canvas != null) {
var currWidth = canvas.clientWidth;
//console.log('zoomin currWidth='+currWidth);
if (currWidth >= 1500) return false;
else {
canvas.style.width = (currWidth + 100) + "px";
//if (currScale < SCALE_MAX)
// currScale++;
//console.log('scale=' + currScale);
}
}
}
function zoomout_canvas() {
if (canvas != null) {
var currWidth = canvas.clientWidth;
if (currWidth <= 100) return false;
else {
canvas.style.width = (currWidth - 100) + "px";
//if (currScale > SCALE_MIN)
// currScale--;
//console.log('scale=' + currScale);
}
}
}
var currImgId = null;
function selectImg(e) {
if (currImgId != null) {
document.getElementById(currImgId).style.border = "none";
}
e.target.style.border = "2px solid orange";
currImgId = (e.target).getAttribute('id');
if (typeof canvas !== 'undefined') {
// the variable is defined
canvas = e.target;
ctx = canvas.getContext("2d");
}
//ctx.drawImage(img, 5, 40, canvas.width, canvas.height);
}
function rotate() {
if (currImgId != null) {
document.getElementById(currImgId).setAttribute("class", "rotated-image");
}
}
var degrees = 0;
function rotateRight() {
console.log('currimgid=' + currImgId);
var img = document.getElementById(currImgId);
degrees = parseInt(img.getAttribute("rotate"));
degrees = (degrees + 90) % 360;
img.style.setProperty('-ms-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('-webkit-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('transform', 'rotate(' + degrees + 'deg)');
img.setAttribute("rotate", degrees);
}
function rotateLeft() {
var img = document.getElementById(currImgId);
degrees = parseInt(img.getAttribute("rotate"));
degrees = (degrees - 90) % 360;
img.style.setProperty('-ms-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('-webkit-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('transform', 'rotate(' + degrees + 'deg)');
img.setAttribute("rotate", degrees);
}
function translate(X, Y) {
console.log('untransformed x=' + X + ', y=' + Y);
// const point = {x: 0, y: 0};
const matrix = ctx.getTransform();
const transformedPoint = {
x: matrix.a * X + matrix.c * Y + matrix.e,
y: matrix.b * X + matrix.d * Y + matrix.f,
};
console.log('transformed x=' + transformedPoint.x + ', y=' + transformedPoint.y);
}
function translateSimple(X, Y) {
//console.log('scalefactor='+scaleFactor);
console.log('untransformed x=' + X + ', y=' + Y);
if (scaleFactor >= 1.0)
console.log('transformed x=' + X / scaleFactor + ', y=' + Y / scaleFactor);
else
console.log('transformed x=' + X * scaleFactor + ', y=' + Y * scaleFactor);
}
function transformSimple(a) {
//return (parseInt(a/(scaleFactor*scaleFactor)));
if (currScale == 0)
return (a);
else
return (a - 16 * (currScale));
}
function draw() {
for (var x = 100; x < 102; x++)
ctx.fillRect(100, x, 4.9, 4.9);
}
.main_bottom {
background-color: #e8e9eb;
display: flex;
align-items: center;
justify-content: space-around;
border: 10px solid #e8e9eb;
border-top: 30px solid #e8e9eb;
height: 90vh;
}
form {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
margin-bottom: 5px;
}
.scrollit {
/*overflow-y: auto;*/
/* overflow-y: scroll;*/
height: 300px;
overflow-x: hidden;
overflow-y: auto;
}
.first {
display: flex;
flex-direction: row;
visibility: hidden;
}
.submit {
display: flex;
flex-direction: row;
}
img {
width: 100%;
max-width: 800px;
height: auto;
display: block;
margin-left: auto;
margin-right: auto;
}
.fix {
height: 300px;
margin-top: 200px;
}
body,
html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
}
#left_panel {
display: flex;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 700px;
background-color: white;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
flex-direction: column;
overflow: scroll;
}
#right_panel {
display: flex;
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 700px;
margin-right: 15px;
background-color: white;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
flex-direction: column;
overflow: scroll;
}
#drag {
position: absolute;
left: -4px;
top: 0;
bottom: 0;
width: 8px;
cursor: w-resize;
}
/*img zooms*/
#navbar {
overflow: hidden;
background-color: #099;
position: fixed;
top: 0;
width: 100%;
padding-top: 3px;
padding-bottom: 3px;
padding-left: 20px;
}
#navbar a {
float: left;
display: block;
color: #666;
text-align: center;
padding-right: 20px;
text-decoration: none;
font-size: 17px;
}
#navbar a:hover {
background-color: #ddd;
color: black;
}
#navbar a.active {
background-color: #4caf50;
color: white;
}
.main {
padding: 16px;
margin-top: 30px;
width: 100%;
height: 100vh;
overflow: auto;
cursor: grab;
cursor: -o-grab;
cursor: -moz-grab;
cursor: -webkit-grab;
}
.main img {
height: auto;
width: auto;
}
.button {
width: 300px;
height: 60px;
}
/*---- toggle switch*/
.switch {
position: relative;
display: inline-block;
width: 30px;
height: 17px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 13px;
width: 13px;
left: 4px;
bottom: 2px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked+.slider {
background-color: #2196f3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196f3;
}
input:checked+.slider:before {
-webkit-transform: translateX(13px);
-ms-transform: translateX(13px);
transform: translateX(13px);
}
/* Rounded sliders */
.slider.round {
border-radius: 17px;
}
.slider.round:before {
border-radius: 50%;
}
.both {
margin-top: 50px;
display: flex;
justify-content: center;
}
<!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">
<link rel="stylesheet" href="./styles.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<title>Order by Picture</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div id="navbar">
<button type="button" onclick="zoomin_canvas()">+</button>
<button type="button" onclick="zoomout_canvas()">-</button>
<button id="rotateRight" onclick="rotateRight()">Right</button>
<button id="rotateLeft" onclick="rotateLeft()">Left</button>
<button id="Button1" onclick="draw()">draw</button
<label> Marking</label>
<label class="switch">
<input type="checkbox" checked onclick="doMarking()" id="mark">
<span class="slider round"></span>
</label>
</div>
<div class="both">
<div class="canvas1">
<canvas id="canvas1" rotate="0" onclick="selectImg(event)" onmousedown="mouseDown(event)" onmouseup="mouseUp(event)" onmousemove="mouseMove(event)">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
<div class="canvas2">
<canvas id="canvas2" rotate="0" onclick="selectImg(event)" onmousedown="mouseDown(event)" onmouseup="mouseUp(event)" onmousemove="mouseMove(event)">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
</div>
</body>
</html>
Don't rotate the canvas
Draw the rotated image on the canvas, rather than rotate the canvas.
When you draw image on the canvas, rotate it, then you can draw over it using the normal mouse coords.
Rotating image on canvas
The code below will draw an image rotated by any amount. The image will be scaled down if needed to ensure it fits the canvas. The function will rotate the image any angle you want.
// ctx is canvas 2D context
// deg in degrees rotated CW from 3 O-clock
// img to render. NOTE image must be loaded first
function drawRotatedImage(ctx, deg, img) {
const w = img.naturalWidth;
const h = img.naturalHeight;
const cw = ctx.canvas.width;
const ch = ctx.canvas.height;
// convert deg to radians
const rad = deg * Math.PI / 180;
// Get vector for rotated xAxis ax, ay. With aax, aay in first quadrant
const ax = Math.cos(rad), aax = Math.abs(ax);
const ay = Math.sin(rad), aay = Math.abs(ay);
// get the rotated width and height of image
const tw = aax * w + aay * h;
const th = aay * w + aax * h;
// get scale so that image fits the canvas. Dont enlarge only reduce if to big
const scale = Math.min(1, cw / tw, ch / th);
// set canvas transform to center of canvas, rotated and scaled to fit
ctx.setTransform(ax * scale, ay * scale, -ay * scale, ax * scale, cw / 2, ch / 2);
// draw image on canvas offset by half its width and height
ctx.drawImage(img, -w / 2, -h / 2);
// restore canvas transform to default
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
Example
Example using the above function to render image to canvas and then use mouse to draw over the image. Click rotate to rotate the image.
const ctx = canvas.getContext("2d");
const mouse = {x: 0, y: 0, b: false, ox: 0, oy: 0};
var rot = 90;
const img = new Image;
img.src = "https://i.stack.imgur.com/C7qq2.png?s=420&g=1";
img.onload = () => rotImage(ctx, rot, img);
resize();
addEventListener("resize", resize);
rotBtn.addEventListener("click", () => img.complete && rotImage(ctx, rot += 90, img));
addEventListener("mousemove", mouseEvent);
addEventListener("mousedown", mouseEvent);
addEventListener("mouseup", mouseEvent);
addEventListener("mouseout", mouseEvent);
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.strokeStyle = "#00F";
img.complete && rotImage(ctx, rot, img);
}
function mouseEvent(e) {
mouse.ox = mouse.x;
mouse.oy = mouse.y;
mouse.x = e.pageX;
mouse.y = e.pageY;
if (e.type === "mousedown") { mouse.b = true }
else if (e.type === "mouseup" || e.type === "mouseout") { mouse.b = false }
mouse.b && drawWithMouse(ctx, mouse);
}
function drawWithMouse(ctx, mouse) {
ctx.beginPath();
ctx.lineTo(mouse.ox, mouse.oy);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
}
function rotImage(ctx, deg, img) {
const cw = ctx.canvas.width, ch = ctx.canvas.height;
const w = img.naturalWidth, h = img.naturalHeight;
const rad = deg * Math.PI / 180;
const ax = Math.cos(rad), aax = Math.abs(ax);
const ay = Math.sin(rad), aay = Math.abs(ay);
const tw = aax * w + aay * h;
const th = aay * w + aax * h;
const sc = Math.min(1, cw / tw, ch / th);
ctx.clearRect(0, 0, cw, ch);
ctx.setTransform(ax * sc, ay * sc, -ay * sc, ax * sc, cw / 2, ch / 2);
ctx.drawImage(img, -w / 2, -h / 2);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
* {font-family: arial;}
button { position: absolute; top: 10px; left: 10px }
canvas { position: absolute; top: 0px; left: 0px }
<canvas id="canvas"></canvas>
<button id="rotBtn">Rotate</button>

sin and cos animations on a curved line with javascript and CSS

I am trying to use sin and cos to animate a CSS image to move on this shape. Can not make the CSS image to move on that curved bezier line.
Can someone assist on how to use sin or cos in so, if a CSS object added, it would move smoothly along such a line?
Here is the code that I tried to make the yellow circle to move on that line with sin and cos math in javascript.
Thanks
var field = document.getElementById("field");
var ball = document.getElementById("ball");
var ball2 = document.getElementById("ball2");
var maxX = field.clientWidth - ball.offsetWidth;
var maxY = field.clientHeight - ball.offsetHeight;
var duration = 5; // seconds
var gridSize = 50; // pixels
var start = null;
function step(timestamp) {
var progress, x, y, y2;
if (start === null)
start = timestamp;
progress = (timestamp - start) / duration / 1000; // percent
x = progress * maxX / gridSize; // x = ƒ(t)
y = 2 * Math.sin(x); // y = ƒ(x)
y2 = 2 * Math.cos(x);
ball.style.left = ball2.style.left = Math.min(maxX, gridSize * x)
+ "px";
ball.style.bottom = maxY / 2 + (gridSize * y) + "px";
ball2.style.bottom = maxY / 2 + (gridSize * y2) + "px";
if (progress >= 1)
start = null; // reset to start position
requestAnimationFrame(step);
}
requestAnimationFrame(step);
#field {
position: absolute;
height: 300px;
width: 300px;
z-index: 50;
top: 20px;
left: 20px;
}
#ball {
position: absolute;
left: 0;
bottom: 50%;
width: 40px;
background: yellow;
z-index: 5;
height: 40px;
border-radius: 200px;
}
#ball2 {
position: absolute;
left: 0;
bottom: 50%;
width: 20px;
height: 20px;
/*background: silver;*/
border-radius: 100px;
}
<div id="field">
<div id="ball"></div>
<div id="ball2"></div>
</div>
requestAnimationFrame calls the given function exactly ONCE
to animate, you need to call requestAnimationFrame within that given function, usually calling the function itself (though more complex animations may call something else, it doesn't matter)
The main point being, you need to call requestAnimationFrame for each frame you want to animate
var field = document.getElementById("field");
var ball = document.getElementById("ball");
var ball2 = document.getElementById("ball2");
var maxX = field.clientWidth - ball.offsetWidth;
var maxY = field.clientHeight - ball.offsetHeight;
var duration = 5; // seconds
var gridSize = 40; // pixels
var start = null;
function step(timestamp) {
var progress, x, y, y2;
if (start === null)
start = timestamp;
progress = (timestamp - start) / duration / 1000; // percent
x = progress * maxX / gridSize; // x = ƒ(t)
y = -2 * Math.cos(x); // y = ƒ(x)
y2 = 2 * Math.cos(x);
ball.style.left = ball2.style.left = Math.min(maxX, gridSize * x) +
"px";
ball.style.bottom = maxY / 2 + (gridSize * y) + "px";
ball2.style.bottom = maxY / 2 + (gridSize * y2) + "px";
if (progress >= 1)
start = null; // reset to start position
requestAnimationFrame(step);
}
requestAnimationFrame(step);
#field {
position: absolute;
height: 300px;
width: 300px;
z-index: 50;
top: 20px;
left: 20px;
}
#ball {
position: absolute;
left: 0;
bottom: 50%;
width: 40px;
background: yellow;
height: 40px;
border-radius: 200px;
}
#ball2 {
position: absolute;
left: 0;
bottom: 50%;
width: 20px;
height: 20px;
background: silver;
border-radius: 100px;
}
<div id="field">
<div id="ball"></div>
<div id="ball2"></div>
</div>

How do I calculate the minimal distance to a rectangle in JavaScript?

I want to calculate the minimal distance to a rectangle in JavaScript:
--------
| | <- Rectangle
--------
* <- Point
But I only found a script to get the distance to the center of a rectangle. Please try to avoid JQuery because I don't want to use it in my code.
Example: (distance to center)
var distance = Infinity,
rect,
out;
document.mouse = {
x: Infinity,
y: Infinity
}
window.addEventListener("load", function(e) { // set vars
rect = document.getElementById("rect");
out = document.getElementById("out");
}, false);
window.addEventListener("mousemove", function(e) {
document.mouse = {
x: e.pageX,
y: e.pageY
} // get mouse position
distance = elementDistanceToCursor(rect) // get distance to element
out.innerHTML = ["distance: ", distance].join(""); // show result
}, false);
function elementDistanceToCursor(elem) { // get distance to element center
var b = elem.getBoundingClientRect();
return Math.floor(
Math.sqrt(
Math.pow(document.mouse.x - (b.left + (elem.offsetWidth / 2)), 2)
+Math.pow(document.mouse.y - (b.top + (elem.offsetHeight / 2)), 2)
)
);
}
div#rect {
width: 200px;
height: 100px;
border: 1px solid black;
background-color: aqua;
margin: auto;
margin-top: 50px;
}
out {
margin: auto;
vertical-align: middle;
text-align: center;
display: block;
height: 20px;
margin-top: 30px;
}
<div id="rect">
<out id="out"></out>
</div>
To compute the minimal distance from a rectangle to a point you use signed distances on each dimension, then compute the sqrt of squared sums.
var distance = Infinity,
rect,
out;
document.mouse = {
x: Infinity,
y: Infinity
}
window.addEventListener("load", function(e) { // set vars
rect = document.getElementById("rect");
out = document.getElementById("out");
}, false);
window.addEventListener("mousemove", function(e) {
document.mouse = {
x: e.pageX,
y: e.pageY
} // get mouse position
distance = elementDistanceToCursor(rect) // get distance to element
out.innerHTML = ["distance: ", distance].join(""); // show result
}, false);
function elementDistanceToCursor(elem) { // get distance to element
var b = elem.getBoundingClientRect();
var dx = 0;
var dy = 0;
//Compute distance to elem in X
if (document.mouse.x < b.left)
dx = b.left - document.mouse.x;
else if (document.mouse.x > b.right)
dx = b.right - document.mouse.x;
//Compute distance to elem in Y
if (document.mouse.y < b.top)
dy = b.top - document.mouse.y;
else if (document.mouse.y > b.bottom)
dy = b.bottom - document.mouse.y;
return Math.floor(Math.sqrt(dx * dx + dy * dy));
}
div#rect {
width: 200px;
height: 100px;
border: 1px solid black;
background-color: aqua;
margin: auto;
margin-top: 50px;
}
out {
margin: auto;
vertical-align: middle;
text-align: center;
display: block;
height: 20px;
margin-top: 30px;
}
<div id="rect">
<out id="out"></out>
</div>

Converting Popmotion example to GreenSock

I'm trying to convert this Popmotion example to GreenSock.
https://codepen.io/popmotion/pen/xVeWmm
var SELECTOR = '.box';
var velocityRange = [-1000, 1000];
var maxRotate = 30;
var smoothing = 100;
var box = ui.select(SELECTOR, {
values: {
x: 0,
y: 0,
rotateY: {
watch: function (actor) {
return actor.values.x.velocity;
},
mapFrom: velocityRange,
mapTo: [-maxRotate, maxRotate],
smooth: smoothing
},
rotateX: {
watch: function (actor) {
return actor.values.y.velocity;
},
mapFrom: velocityRange,
mapTo: [maxRotate, -maxRotate],
smooth: smoothing
}
}
});
var track2D = new ui.Track({
values: {
x: {},
y: {}
}
});
var springBack = new ui.Simulate({
simulate: 'spring',
spring: 500,
friction: 0.3,
values: {
x: 0,
y: 0
}
});
$('body').on('touchstart mousedown', SELECTOR, function (e) {
e.preventDefault();
box.start(track2D, e);
});
$('body').on('touchend mouseup', function () {
box.start(springBack);
});
Being a total noob at GreenSock, is this easy to do? Does GreenSock have actors and simulators?
I have never used GreenSock to make continuous dynamic animations (maybe it is possible, I am not an expert in GreenSock). I prefer to left this library to make a specific animation. In the next example, I've tried to replicate the same Popmotion effect you have posted using my own calculations and I just use the animation library to return the box to its original place. I think that it can help you in your purpose:
I've removed the vendor prefixes to make the code easier to read, but the CodePen example has the prefixes.
HTML Code:
<div id="container">
<div class="box"></div>
</div>
CSS Code
html {
height: 100%;
}
body {
background: #e25875;
height: 100%;
}
#container {
height: 100%;
perspective: 700;
perspective-origin: 50% 50%;
position: relative;
transform-style: preserve-3d;
width: 100%;
}
.box {
background: white;
border-radius: 4px;
height: 150px;
left: 50%;
margin-left: -75px;
margin-top: -75px;
position: absolute;
cursor: pointer;
top: 50%;
will-change: transform;
width: 150px;
}
JavaScript Code:
//---Variables
var doc = document,
box = doc.querySelector(".box"),
startX = 0,
startY = 0,
posX = 0,
posY = 0,
speedX = 0,
speedY = 0,
obj = {x: 0, y: 0, speedX: 0, speedY: 0};
//---Main Events
box.addEventListener("mousedown", startMove);
doc.addEventListener("mouseup", stopMove);
//---Start the movement
function startMove (evt) {
startX = evt.pageX;
startY = evt.pageY;
//---Add the mouse move events
doc.addEventListener("mousemove", updatePosition);
}
//---Update variables
function updatePosition (evt) {
speedX = (evt.pageX - posX) * 5;
speedY = (evt.pageY - posY) * 5;
if (speedX < -45) { speedX = -45 }
if (speedX > 45) { speedX = 45 }
if (speedY < -45) { speedY = -45 }
if (speedY > 45) { speedY = 45 }
posX = evt.pageX;
posY = evt.pageY;
obj.x += (posX - startX - obj.x) * .15;
obj.y += (posY - startY - obj.y) * .15;
obj.speedX += (speedX - obj.speedX) * .15;
obj.speedY += (speedY - obj.speedY) * .15;
updateTransform();
}
//---Stop movement, returns the box to its place
function stopMove () {
TweenLite.to(obj, 0.75, {
ease: Elastic.easeOut.config(1, 0.3),
x: 0,
y: 0,
speedX: 0,
speedY: 0,
onUpdate: updateTransform
});
doc.removeEventListener("mousemove", updatePosition);
}
//---Update the box transformations
function updateTransform () {
var transformStr = "translate(" + obj.x + "px, " + obj.y + "px) rotateX(" + (-obj.speedY) + "deg) rotateY(" + obj.speedX + "deg)";
box.style.transform = transformStr;
}
Here you have a CodePen with a working example.
EDIT: I've updated the CodePen to work with Touch Events.
CodePen

Categories

Resources