Let’s say I have a video element where I want to handle mouse events:
const v = document.querySelector('video');
v.onclick = (ev) => {
ev.preventDefault();
console.info(`x=${event.offsetX}, y=${event.offsetY}`);
};
document.querySelector('#play').onclick =
(ev) => v.paused ? v.play() : v.pause();
document.querySelector('#fit').onchange =
(ev) => v.style.objectFit = ev.target.value;
<button id="play">play/pause</button>
<label>object-fit: <select id="fit">
<option>contain</option>
<option>cover</option>
<option>fill</option>
<option>none</option>
<option>scale-down</option>
</select></label>
<video
style="width: 80vw; height: 80vh; display: block; margin: 0 auto; background: pink;"
src="https://www.w3schools.com/html/mov_bbb.mp4"
>
</video>
The event object gives me coordinates relative to the bounding box of the player element (pink). How can I convert between those and coordinates of the actual scaled picture?
I don’t particularly care if overflowing coordinates (those beyond the picture frame) are clipped or extrapolated, I don’t mind rounding errors, and I don’t even care much in which units I get them (percentages or pixels). I would, however, like the solution to be robust to changes to object-fit and object-position CSS properties, and I also want to be able to convert bare coordinates without a mouse event.
How can I perform such a conversion?
I don't think there is any native API that would give that to us, which means that we have to compute this ourselves, for every value of object-fit.
Below is a quick implementation I made, which I didn't test thoroughly but seems to work quite well.
Note that the demo uses a <canvas> and not a <video> but object-fit and object-position actually work the same there, so you can use ghe same function in your case, the <canvas> allows to check we're correct easily.
// Some helpers
/**
* Returns the intrinsic* width & height of most media sources in the Web API
* (at least the closest we can get to it)
*/
function getResourceDimensions(source) {
if (source.videoWidth) {
return { width: source.videoWidth, height: source.videoHeight };
}
if (source.naturalWidth) {
return { width: source.naturalWidth, height: source.naturalHeight };
}
if (source.width) {
return { width: source.width, height: source.height };
}
return null;
}
/**
* Parses the component values of "object-position"
* Returns the position in px
*/
function parsePositionAsPx(str, bboxSize, objectSize) {
const num = parseFloat(str);
if (str.match(/%$/)) {
const ratio = num / 100;
return (bboxSize * ratio) - (objectSize * ratio);
}
return num;
}
function parseObjectPosition(position, bbox, object) {
const [left, top] = position.split(" ");
return {
left: parsePositionAsPx(left, bbox.width, object.width),
top: parsePositionAsPx(top, bbox.height, object.height)
};
}
// The actual implementation
function relativeToObject(x, y, elem) {
let { objectFit, objectPosition } = getComputedStyle(elem);
const bbox = elem.getBoundingClientRect();
const object = getResourceDimensions(elem);
if (objectFit === "scale-down") {
objectFit = (bbox.width < object.width || bbox.height < object.height)
? "contain" : "none";
}
if (objectFit === "none") {
const {left, top} = parseObjectPosition(objectPosition, bbox, object);
return {
x: x - left,
y: y - top
};
}
if (objectFit === "contain") {
const objectRatio = object.height / object.width;
const bboxRatio = bbox.height / bbox.width;
const outWidth = bboxRatio > objectRatio
? bbox.width : bbox.height / objectRatio;
const outHeight = bboxRatio > objectRatio
? bbox.width * objectRatio : bbox.height;
const {left, top} = parseObjectPosition(objectPosition, bbox, {width: outWidth, height: outHeight});
return {
x: (x - left) * (object.width / outWidth),
y: (y - top) * (object.height / outHeight)
};
}
if (objectFit === "fill") {
const xRatio = object.width / bbox.width;
const yRatio = object.height / bbox.height;
return {
x: x * xRatio,
y: y * yRatio
};
}
if (objectFit === "cover") {
const minRatio = Math.min(bbox.width / object.width, bbox.height / object.height);
let outWidth = object.width * minRatio;
let outHeight = object.height * minRatio;
let outRatio = 1;
if (outWidth < bbox.width) {
outRatio = bbox.width / outWidth;
}
if (Math.abs(outRatio - 1) < 1e-14 && outHeight < bbox.height) {
outRatio = bbox.height / outHeight;
}
outWidth *= outRatio;
outHeight *= outRatio;
const { left, top } = parseObjectPosition(objectPosition, bbox, {width: outWidth, height: outHeight});
return {
x: (x - left) * (object.width / outWidth),
y: (y - top) * (object.height / outHeight)
};
}
};
// Example: draw a rectangle around the mouse position
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
function init() {
ctx.fillStyle = ctx.createRadialGradient(canvas.width/2, canvas.height/2, 0, canvas.width/2, canvas.height/2, Math.hypot(canvas.width/2, canvas.height/2));
ctx.fillStyle.addColorStop(0, "red");
ctx.fillStyle.addColorStop(1, "green");
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
canvas.onmousemove = (evt) => {
const canvasRect = canvas.getBoundingClientRect();
const mouseX = evt.clientX - canvasRect.left;
const mouseY = evt.clientY - canvasRect.top;
const {x, y} = relativeToObject(mouseX, mouseY, canvas);
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = "white";
ctx.strokeRect(x - 5, y - 5, 10, 10);
};
// To update our test settings
document.getElementById("object_fit_select").onchange = (evt) => {
canvas.style.setProperty("--object-fit", evt.target.value);
};
document.getElementById("object_position_x").oninput = (evt) => {
canvas.style.setProperty("--object-position-x", evt.target.value);
};
document.getElementById("object_position_y").oninput = (evt) => {
canvas.style.setProperty("--object-position-y", evt.target.value);
};
document.getElementById("canvas_width").oninput = (evt) => {
canvas.width = evt.target.value;
init();
};
document.getElementById("canvas_height").oninput = (evt) => {
canvas.height = evt.target.value;
init();
};
init();
canvas {
--object-fit: contain;
--object-position-x: center;
--object-position-y: center;
width: 500px;
height: 500px;
object-fit: var(--object-fit);
object-position: var(--object-position-x) var(--object-position-y);
outline: 1px solid;
width: 100%;
height: 100%;
background: pink;
}
.resizable {
resize: both;
overflow: hidden;
width: 500px;
height: 500px;
outline: 1px solid;
}
<label>object-fit: <select id="object_fit_select">
<option>contain</option>
<option>cover</option>
<option>fill</option>
<option>none</option>
<option>scale-down</option>
</select></label><br>
<label>x-position: <input id="object_position_x" value="center"></label><br>
<label>y-position: <input id="object_position_y" value="center"></label><br>
<label>canvas width: <input id="canvas_width" value="600"></label><br>
<label>canvas height: <input id="canvas_height" value="150"></label><br>
<div class="resizable">
<canvas id="canvas" width="600" height="150"></canvas>
</div>
jQuery('#carregar').click(function() {
var canvas = document.getElementById('canvas');
var image = document.getElementById('image');
var element = canvas.getContext("2d");
element.clearRect(0, 0, canvas.width, canvas.height);
element.drawImage(image, 0, 0, 300, 300);
});
jsfiddle.net/braziel/nWyDE/
I have a problem to rotate an image 90 ° to the right or to the left.
I use an image on the canvas, the same screen will have several canvas equal to that of the example, but I left it as close as possible to the project.
I ask, how do I rotate the image 90 ° to the left or right when I click "Rotate Left" and "Rotate Right"?
I tried several codes on the internet but none worked.
You can use canvas’ context.translate & context.rotate to do rotate your image
Here’s a function to draw an image that is rotated by the specified degrees:
function drawRotated(degrees){
context.clearRect(0,0,canvas.width,canvas.height);
// save the unrotated context of the canvas so we can restore it later
// the alternative is to untranslate & unrotate after drawing
context.save();
// move to the center of the canvas
context.translate(canvas.width/2,canvas.height/2);
// rotate the canvas to the specified degrees
context.rotate(degrees*Math.PI/180);
// draw the image
// since the context is rotated, the image will be rotated also
context.drawImage(image,-image.width/2,-image.width/2);
// we’re done with the rotating so restore the unrotated context
context.restore();
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/6ZsCz/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var angleInDegrees=0;
var image=document.createElement("img");
image.onload=function(){
ctx.drawImage(image,canvas.width/2-image.width/2,canvas.height/2-image.width/2);
}
image.src="houseicon.png";
$("#clockwise").click(function(){
angleInDegrees+=30;
drawRotated(angleInDegrees);
});
$("#counterclockwise").click(function(){
angleInDegrees-=30;
drawRotated(angleInDegrees);
});
function drawRotated(degrees){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(degrees*Math.PI/180);
ctx.drawImage(image,-image.width/2,-image.width/2);
ctx.restore();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas><br>
<button id="clockwise">Rotate right</button>
<button id="counterclockwise">Rotate left</button>
</body>
</html>
Quickest 2D context image rotation method
A general purpose image rotation, position, and scale.
// no need to use save and restore between calls as it sets the transform rather
// than multiply it like ctx.rotate ctx.translate ctx.scale and ctx.transform
// Also combining the scale and origin into the one call makes it quicker
// x,y position of image center
// scale scale of image
// rotation in radians.
function drawImage(image, x, y, scale, rotation){
ctx.setTransform(scale, 0, 0, scale, x, y); // sets scale and origin
ctx.rotate(rotation);
ctx.drawImage(image, -image.width / 2, -image.height / 2);
}
If you wish to control the rotation point use the next function
// same as above but cx and cy are the location of the point of rotation
// in image pixel coordinates
function drawImageCenter(image, x, y, cx, cy, scale, rotation){
ctx.setTransform(scale, 0, 0, scale, x, y); // sets scale and origin
ctx.rotate(rotation);
ctx.drawImage(image, -cx, -cy);
}
To reset the 2D context transform
ctx.setTransform(1,0,0,1,0,0); // which is much quicker than save and restore
Thus to rotate image to the left (anti clockwise) 90 deg
drawImage(image, canvas.width / 2, canvas.height / 2, 1, - Math.PI / 2);
Thus to rotate image to the right (clockwise) 90 deg
drawImage(image, canvas.width / 2, canvas.height / 2, 1, Math.PI / 2);
Example draw 500 images translated rotated scaled
var image = new Image;
image.src = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1";
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
document.body.appendChild(canvas);
var w,h;
function resize(){ w = canvas.width = innerWidth; h = canvas.height = innerHeight;}
resize();
window.addEventListener("resize",resize);
function rand(min,max){return Math.random() * (max ?(max-min) : min) + (max ? min : 0) }
function DO(count,callback){ while (count--) { callback(count) } }
const sprites = [];
DO(500,()=>{
sprites.push({
x : rand(w), y : rand(h),
xr : 0, yr : 0, // actual position of sprite
r : rand(Math.PI * 2),
scale : rand(0.1,0.25),
dx : rand(-2,2), dy : rand(-2,2),
dr : rand(-0.2,0.2),
});
});
function drawImage(image, spr){
ctx.setTransform(spr.scale, 0, 0, spr.scale, spr.xr, spr.yr); // sets scales and origin
ctx.rotate(spr.r);
ctx.drawImage(image, -image.width / 2, -image.height / 2);
}
function update(){
var ihM,iwM;
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,w,h);
if(image.complete){
var iw = image.width;
var ih = image.height;
for(var i = 0; i < sprites.length; i ++){
var spr = sprites[i];
spr.x += spr.dx;
spr.y += spr.dy;
spr.r += spr.dr;
iwM = iw * spr.scale * 2 + w;
ihM = ih * spr.scale * 2 + h;
spr.xr = ((spr.x % iwM) + iwM) % iwM - iw * spr.scale;
spr.yr = ((spr.y % ihM) + ihM) % ihM - ih * spr.scale;
drawImage(image,spr);
}
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
The other solution works great for square images. Here is a solution that will work for an image of any dimension. The canvas will always fit the image rather than the other solution which may cause portions of the image to be cropped off.
var canvas;
var angleInDegrees=0;
var image=document.createElement("img");
image.onload=function(){
drawRotated(0);
}
image.src="http://greekgear.files.wordpress.com/2011/07/bob-barker.jpg";
$("#clockwise").click(function(){
angleInDegrees+=90 % 360;
drawRotated(angleInDegrees);
});
$("#counterclockwise").click(function(){
if(angleInDegrees == 0)
angleInDegrees = 270;
else
angleInDegrees-=90 % 360;
drawRotated(angleInDegrees);
});
function drawRotated(degrees){
if(canvas) document.body.removeChild(canvas);
canvas = document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.style.width="20%";
if(degrees == 90 || degrees == 270) {
canvas.width = image.height;
canvas.height = image.width;
} else {
canvas.width = image.width;
canvas.height = image.height;
}
ctx.clearRect(0,0,canvas.width,canvas.height);
if(degrees == 90 || degrees == 270) {
ctx.translate(image.height/2,image.width/2);
} else {
ctx.translate(image.width/2,image.height/2);
}
ctx.rotate(degrees*Math.PI/180);
ctx.drawImage(image,-image.width/2,-image.height/2);
document.body.appendChild(canvas);
}
http://jsfiddle.net/6ZsCz/1588/
This is the simplest code to draw a rotated and scaled image:
function drawImage(ctx, image, x, y, w, h, degrees){
ctx.save();
ctx.translate(x+w/2, y+h/2);
ctx.rotate(degrees*Math.PI/180.0);
ctx.translate(-x-w/2, -y-h/2);
ctx.drawImage(image, x, y, w, h);
ctx.restore();
}
As #markE mention in his answer
the alternative is to untranslate & unrotate after drawing
It is much faster than context save and restore.
Here is an example
// translate and rotate
this.context.translate(x,y);
this.context.rotate(radians);
this.context.translate(-x,-y);
this.context.drawImage(...);
// untranslate and unrotate
this.context.translate(x, y);
this.context.rotate(-radians);
this.context.translate(-x,-y);
This is full degree image rotation code. I recommend you to check the below example app in the jsfiddle.
https://jsfiddle.net/casamia743/xqh48gno/
The process flow of this example app is
load Image, calculate boundaryRad
create temporary canvas
move canvas context origin to joint position of the projected rect
rotate canvas context with input degree amount
use canvas.toDataURL method to make image blob
using image blob, create new Image element and render
function init() {
...
image.onload = function() {
app.boundaryRad = Math.atan(image.width / image.height);
}
...
}
/**
* NOTE : When source rect is rotated at some rad or degrees,
* it's original width and height is no longer usable in the rendered page.
* So, calculate projected rect size, that each edge are sum of the
* width projection and height projection of the original rect.
*/
function calcProjectedRectSizeOfRotatedRect(size, rad) {
const { width, height } = size;
const rectProjectedWidth = Math.abs(width * Math.cos(rad)) + Math.abs(height * Math.sin(rad));
const rectProjectedHeight = Math.abs(width * Math.sin(rad)) + Math.abs(height * Math.cos(rad));
return { width: rectProjectedWidth, height: rectProjectedHeight };
}
/**
* #callback rotatedImageCallback
* #param {DOMString} dataURL - return value of canvas.toDataURL()
*/
/**
* #param {HTMLImageElement} image
* #param {object} angle
* #property {number} angle.degree
* #property {number} angle.rad
* #param {rotatedImageCallback} cb
*
*/
function getRotatedImage(image, angle, cb) {
const canvas = document.createElement('canvas');
const { degree, rad: _rad } = angle;
const rad = _rad || degree * Math.PI / 180 || 0;
debug('rad', rad);
const { width, height } = calcProjectedRectSizeOfRotatedRect(
{ width: image.width, height: image.height }, rad
);
debug('image size', image.width, image.height);
debug('projected size', width, height);
canvas.width = Math.ceil(width);
canvas.height = Math.ceil(height);
const ctx = canvas.getContext('2d');
ctx.save();
const sin_Height = image.height * Math.abs(Math.sin(rad))
const cos_Height = image.height * Math.abs(Math.cos(rad))
const cos_Width = image.width * Math.abs(Math.cos(rad))
const sin_Width = image.width * Math.abs(Math.sin(rad))
debug('sin_Height, cos_Width', sin_Height, cos_Width);
debug('cos_Height, sin_Width', cos_Height, sin_Width);
let xOrigin, yOrigin;
if (rad < app.boundaryRad) {
debug('case1');
xOrigin = Math.min(sin_Height, cos_Width);
yOrigin = 0;
} else if (rad < Math.PI / 2) {
debug('case2');
xOrigin = Math.max(sin_Height, cos_Width);
yOrigin = 0;
} else if (rad < Math.PI / 2 + app.boundaryRad) {
debug('case3');
xOrigin = width;
yOrigin = Math.min(cos_Height, sin_Width);
} else if (rad < Math.PI) {
debug('case4');
xOrigin = width;
yOrigin = Math.max(cos_Height, sin_Width);
} else if (rad < Math.PI + app.boundaryRad) {
debug('case5');
xOrigin = Math.max(sin_Height, cos_Width);
yOrigin = height;
} else if (rad < Math.PI / 2 * 3) {
debug('case6');
xOrigin = Math.min(sin_Height, cos_Width);
yOrigin = height;
} else if (rad < Math.PI / 2 * 3 + app.boundaryRad) {
debug('case7');
xOrigin = 0;
yOrigin = Math.max(cos_Height, sin_Width);
} else if (rad < Math.PI * 2) {
debug('case8');
xOrigin = 0;
yOrigin = Math.min(cos_Height, sin_Width);
}
debug('xOrigin, yOrigin', xOrigin, yOrigin)
ctx.translate(xOrigin, yOrigin)
ctx.rotate(rad);
ctx.drawImage(image, 0, 0);
if (DEBUG) drawMarker(ctx, 'red');
ctx.restore();
const dataURL = canvas.toDataURL('image/jpg');
cb(dataURL);
}
function render() {
getRotatedImage(app.image, {degree: app.degree}, renderResultImage)
}
I built an image uploader that resizes the image in the background, and also allows the user to rotate the image 90 degrees left or right. This isn't something that is solved with just a few lines of code, so you will want to checkout the jsfiddle https://jsfiddle.net/alienbush/z02jatnr/6/. I also included the complete code below.
The main drawing function looks like this:
let drawOptimizedImage = function (canvas, image, maxSize, rotationDirection) {
let degrees = updateRotationDegrees(rotationDirection)
let newSize = determineSize(image.width, image.height, maxSize.width, maxSize.height, degrees)
canvas.width = newSize.width
canvas.height = newSize.height
let ctx = canvas.getContext('2d')
ctx.save()
ctx.clearRect(0, 0, canvas.width, canvas.height)
if (degrees === 0) {
ctx.drawImage(image, 0, 0, newSize.width, newSize.height)
}
else {
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate(degrees * Math.PI / 180)
if (Math.abs(degrees) === 180) {
ctx.drawImage(image, -newSize.width / 2, -newSize.height / 2, newSize.width, newSize.height)
}
else { // 90 or 270 degrees (values for width and height are swapped for these rotation positions)
ctx.drawImage(image, -newSize.height / 2, -newSize.width / 2, newSize.height, newSize.width)
}
}
ctx.restore()
}
Here's the complete code:
let imgPreview = document.getElementById('imgPreview')
let canvas = document.getElementById('canvas')
let statusMessage = document.getElementById('statusMessage')
let img = new Image
let maxSize = {
width: 800,
height: 600
}
let rotationDegrees = 0
// canvas.toBlob Polyfill from https://gist.github.com/salzhrani/02a6e807f24785a4d34b
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function(callback, type, quality) {
var bin = atob(this.toDataURL(type, quality).split(',')[1]),
len = bin.length,
len32 = len >> 2,
a8 = new Uint8Array(len),
a32 = new Uint32Array(a8.buffer, 0, len32);
for (var i = 0, j = 0; i < len32; i++) {
a32[i] = bin.charCodeAt(j++) |
bin.charCodeAt(j++) << 8 |
bin.charCodeAt(j++) << 16 |
bin.charCodeAt(j++) << 24;
}
var tailLength = len & 3;
while (tailLength--) {
a8[j] = bin.charCodeAt(j++);
}
callback(new Blob([a8], {
'type': type || 'image/png'
}));
}
});
}
document.getElementById('fileInput').addEventListener('change', function(e) {
if (!e.target.files.length) {
return
}
let file = e.target.files[0]
if (isValidMIME(file, ['image/bmp', 'image/jpeg', 'image/png'])) {
img.src = window.URL.createObjectURL(file)
} else {
alert('Invalid file type. The image file must be one of the following: .jpg .jpeg .png .bmp')
}
})
let isValidMIME = function(file, MIMEtypes) {
for (let i = 0; i < MIMEtypes.length; i++) {
if (MIMEtypes[i] === file.type) {
return true
}
}
return false
}
img.addEventListener('load', function() {
rotationDegrees = 0
removeStatusMessage()
drawOptimizedImage(canvas, img, maxSize)
updateImgPreview(canvas, imgPreview)
})
let removeStatusMessage = function() {
statusMessage.textContent = ''
statusMessage.style.display = 'none'
}
let drawOptimizedImage = function(canvas, image, maxSize, rotationDirection) {
let degrees = updateRotationDegrees(rotationDirection)
let newSize = determineSize(image.width, image.height, maxSize.width, maxSize.height, degrees)
canvas.width = newSize.width
canvas.height = newSize.height
let ctx = canvas.getContext('2d')
ctx.save()
ctx.clearRect(0, 0, canvas.width, canvas.height)
if (degrees === 0) {
ctx.drawImage(image, 0, 0, newSize.width, newSize.height)
} else {
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate(degrees * Math.PI / 180)
if (Math.abs(degrees) === 180) {
ctx.drawImage(image, -newSize.width / 2, -newSize.height / 2, newSize.width, newSize.height)
} else { // 90 or 270 degrees (values for width and height are swapped for these rotation positions)
ctx.drawImage(image, -newSize.height / 2, -newSize.width / 2, newSize.height, newSize.width)
}
}
ctx.restore()
}
let updateRotationDegrees = function(rotationDirection) {
if (rotationDirection === 'clockwise') {
rotationDegrees += 90
} else if (rotationDirection === 'anticlockwise') {
rotationDegrees -= 90
}
if (Math.abs(rotationDegrees) === 360) {
rotationDegrees = 0
}
return rotationDegrees
}
let determineSize = function(width, height, maxW, maxH, degrees) {
let w, h;
degrees = Math.abs(degrees)
if (degrees === 90 || degrees === 270) { // values for width and height are swapped for these rotation positions
w = height
h = width
} else {
w = width
h = height
}
if (w > h) {
if (w > maxW) {
h = h * maxW / w
w = maxW
}
} else {
if (h > maxH) {
w = w * maxH / h
h = maxH
}
}
return {
width: w,
height: h
}
}
let updateImgPreview = function(canvas, div) {
if (canvas.width < div.clientWidth && canvas.height < div.clientHeight) {
div.style.backgroundSize = 'auto'
} else {
div.style.backgroundSize = 'contain'
}
div.style.backgroundImage = 'url(' + canvas.toDataURL() + ')'
}
document.getElementById('clockwiseBtn').addEventListener('click', function() {
removeStatusMessage()
drawOptimizedImage(canvas, img, maxSize, 'clockwise')
updateImgPreview(canvas, imgPreview)
})
document.getElementById('anticlockwiseBtn').addEventListener('click', function() {
removeStatusMessage()
drawOptimizedImage(canvas, img, maxSize, 'anticlockwise')
updateImgPreview(canvas, imgPreview)
})
document.getElementById('uploadBtn').addEventListener('click', function() {
let fileInput = document.getElementById('fileInput')
if (!fileInput.files.length) {
alert('Please choose a file first');
return;
}
let formData = new FormData()
formData.append('fileName', 'yourCustomFileNameHere')
canvas.toBlob(function(blob) {
formData.append('image', blob)
let url = 'theURLtoSendTheFileTo'
sendForm(url, formData, doAfterUploadSuccess)
}, 'image/jpeg', 1.0)
})
let sendForm = function(url, formData, callback) {
// Simulating upload. Use the commented code below for a real upload.
statusMessage.style.display = 'block'
statusMessage.textContent = 'Uploading, please wait...'
setTimeout(callback, 2000)
// let xhr = new XMLHttpRequest()
// addUploadListeners(xhr)
// xhr.open('POST', url, true)
// xhr.onload = function () {
// if (xhr.status == 200) {
// if (callback) { callback(xhr) }
// }
// else if (xhr.status === 0) {
// alert('No response from server. Check network connection.')
// }
// else {
// alert('There was a problem uploading: ' + xhr.statusText)
// }
// }
// statusMessage.style.display = 'block'
// xhr.send(formData)
}
let addUploadListeners = function(xhr) {
xhr.addEventListener('loadstart', function(e) {
statusMessage.textContent = 'Uploading, please wait...'
})
xhr.addEventListener('abort', function(e) {
statusMessage.textContent = 'Aborted upload'
})
xhr.addEventListener('error', function(e) {
statusMessage.textContent = 'Error during upload'
})
}
let doAfterUploadSuccess = function(xhr) {
statusMessage.textContent = 'Success!'
}
body {
background-color: lightgray;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 11pt;
font-weight: 400;
-webkit-font-smoothing: antialiased;
margin: 0;
}
button {
outline: none !important;
border-style: none;
background-color: rgb(115, 115, 250);
color: white;
padding: 10px 15px 12px 15px;
cursor: pointer;
border-radius: 2px;
font: inherit;
}
.canvas {
/* You can use display: none; to hide the canvas. The image will upload the same, whether or not the canvas is diplayed. */
display: block;
margin: 0px auto 40px auto;
}
.card {
background: white;
border-radius: 2px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.img-form {
padding: 15px 15px 0px 15px;
width: 320px;
margin: 0 auto;
}
.img-uploader-panel {
padding: 10px;
width: 340px;
margin: 0px auto 20px auto;
}
.img-uploader-header {
margin-top: 5px;
text-align: center;
}
.img-preview {
display: flex;
background-repeat: no-repeat;
background-position-x: center;
background-position-y: center;
background-size: contain;
border: 1px solid rgb(160, 160, 160);
width: 320px;
height: 320px;
margin: 0 auto;
}
.status-message {
display: none;
align-self: flex-end;
margin: 0;
line-height: 50px;
background-color: rgba(0, 0, 0, 0.5);
color: white;
width: 100%;
text-align: center;
}
.uploader-btn-panel {
display: flex;
padding-top: 10px;
justify-content: center;
align-items: center;
}
.rotate-btn {
font-size: 32px;
padding: 5px 12px 9px 13px;
margin-right: 10px;
background-color: transparent;
color: rgba(83, 83, 249, 1);
}
.clockwise-btn {
transform: rotate(90deg);
}
.anticlockwise-btn {
transform: rotate(270deg);
}
.upload-btn {
margin-left: 20px;
}
<form action="post" id="imgForm" class="img-form">
<label for="fileInput">Add an image:</label><br>
<input type="file" name="fileInput" id="fileInput" accept=".jpg, .jpeg, .png, .bmp">
</form><br>
<div class="img-uploader-panel card">
<p class="img-uploader-header">Image Preview</p>
<div id="imgPreview" class="img-preview">
<p id="statusMessage" class="status-message"></p>
</div>
<div class="uploader-btn-panel">
<button id="anticlockwiseBtn" class="anticlockwise-btn rotate-btn">↺</button>
<button id="clockwiseBtn" class="clockwise-btn rotate-btn">↻</button>
<button id="uploadBtn" class="upload-btn">Upload</button>
</div>
</div>
<canvas id="canvas" class="canvas"></canvas>
Here is Something I did
var ImgRotator = {
angle:parseInt(45),
image:{},
src:"",
canvasID:"",
intervalMS:parseInt(500),
jump:parseInt(5),
start_action:function(canvasID, imgSrc, interval, jumgAngle){
ImgRotator.jump = jumgAngle;
ImgRotator.intervalMS = interval;
ImgRotator.canvasID = canvasID;
ImgRotator.src = imgSrc ;
var image = new Image();
var canvas = document.getElementById(ImgRotator.canvasID);
image.onload = function() {
ImgRotator.image = image;
canvas.height = canvas.width = Math.sqrt( image.width* image.width+image.height*image.height);
window.setInterval(ImgRotator.keepRotating,ImgRotator.intervalMS);
//theApp.keepRotating();
};
image.src = ImgRotator.src;
},
keepRotating:function(){
ImgRotator.angle+=ImgRotator.jump;
var canvas = document.getElementById(ImgRotator.canvasID);
var ctx = canvas.getContext("2d");
ctx.save();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(ImgRotator.angle*Math.PI/180);
ctx.drawImage(ImgRotator.image, -ImgRotator.image.width/2,-ImgRotator.image.height/2);
ctx.restore();
}
}
usage
ImgRotator.start_action("canva",
"data:image/jpeg;base64,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",
500,15
);
HTML
<canvas id="canva" width="350" height="350" style="border:solid thin black;"></canvas>
#Steve Farthing's answer is absolutely right.
But if you rotate more than 4 times then the image will get cropped from both the side.
For that you need to do like this.
$("#clockwise").click(function(){
angleInDegrees+=90 % 360;
drawRotated(angleInDegrees);
if(angleInDegrees == 360){ // add this lines
angleInDegrees = 0
}
});
Then you will get the desired result. Thanks. Hope this will help someone :)
Why not do it for the entire page. At page load detect all images and continuously rotate all of them.
var RotationCollection = {
rotators: [],
start_action: function (showBorders, isoverlap) {
try {
var canvasTemplate = '<canvas id="_ID_" width="350" height="350" ></canvas>';
var ja = 5;
$.each($("img"), function (index, val) {
var newID = "can_" + index;
var can = canvasTemplate.replace("_ID_", newID);
if (showBorders == true) $(can).insertAfter($(val)).css({ "border": "solid thin black", "box-shadow": "5px 5px 10px 2px black", "border-raduis": "15px" });
else $(can).insertAfter($(val));
$(val).remove();
var curRot = new RotationClass(newID, $(val).attr('src'), ja * ((0 == index % 2) ? -1 : 1), isoverlap);
RotationCollection.rotators[index] = curRot;
ja += 5;
//return false;
});
window.setInterval(function () {
$.each(RotationCollection.rotators, function (index, value) {
value.drawRotatedImage();
})
}, 500);
}
catch (err) {
console.log(err.message);
}
}
};
function RotationClass(canvasID, imgSrc, jumgAngle, overlap) {
var self = this;
self.overlap = overlap;
self.angle = parseInt(45);
self.image = {};
self.src = imgSrc;
self.canvasID = canvasID;
self.jump = parseInt(jumgAngle);
self.start_action = function () {
var image = new Image();
var canvas = document.getElementById(self.canvasID);
image.onload = function () {
self.image = image;
canvas.height = canvas.width = Math.sqrt(image.width * image.width + image.height * image.height);
self.drawRotatedImage(self);
};
image.src = self.src;
}
self.start_action();
this.drawRotatedImage = function () {
var self = this;
self.angle += self.jump;
var canvas = document.getElementById(self.canvasID);
var ctx = canvas.getContext("2d");
ctx.save();
if (self.overlap) ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(self.angle * Math.PI / 180);
ctx.drawImage(self.image, -self.image.width / 2, -self.image.height / 2);
ctx.restore();
}
}
var theApp = {
start_Action: function () {
RotationCollection.start_action(true, true);
}
};
$(document).ready(theApp.start_Action);
Please check out for theApp.start_Action where all action begins
The HTML can be as follows:
<p>
Deepika Padukone.<br />
<img alt="deepika" src="data:image/jpeg;base64,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" />
</p>
<p>
Priyanka Chopra.<br />
<img alt="Priyanka" src="data:image/jpeg;base64,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" />
</p>
Some options to overlap rotations, borders are also added
To rotate and fill (stretch to fit), try this fiddle which uses the corner of the canvas for a start point instead of the center and can rotate 90, 180 and 270 degrees.
Note: the fiddle is stretching a 200 * 300 image to fit a 600 * 650 canvas
const canvas = document.getElementById('canvas');
const image = document.getElementById('source');
const Rotation = {
None: 0,
Right: 90,
Flip: 180,
Left: 270
};
const noRotation = () => Rotate(Rotation.None);
const rotateRight = () => Rotate(Rotation.Right);
const rotateLeft = () => Rotate(Rotation.Left);
const flip = () => Rotate(Rotation.Flip);
const Rotate = (orientation) => rotateImage(canvas, image, orientation);
function rotateImage(canvas, image, rotation){
const rotate = correctRotation(rotation);
const context = canvas.getContext('2d');
let offsetX = 0;
let offsetY = 0;
let displacementX = canvas.width;
let displacementY = canvas.height;
if (rotate === Rotation.Left || rotate === Rotation.Right){
displacementX = canvas.height;
displacementY = canvas.width;
}
switch(rotate) {
case Rotation.Flip:
offsetX = canvas.width;
offsetY = canvas.height;
break;
case Rotation.Left:
offsetY = canvas.height;
break;
case Rotation.Right:
offsetX = canvas.width;
break;
}
context.setTransform(1, 0, 0, 1, offsetX, offsetY);
context.rotate(rotate * Math.PI / 180);
context.drawImage(image, 0,0, displacementX, displacementY )
}
function correctRotation(rotation) {
return !rotation ? Rotation.None
: rotation < Rotation.Flip ? Rotation.Right
: rotation < Rotation.Left ? Rotation.Flip
: Rotation.Left;
}
image.addEventListener('load', e => noRotation() );
https://jsfiddle.net/0unyh7ck/8/
I'm making a HTML5 Canvas Game with a rectangle that moves around the canvas. The objective is to dodge multiple Balls moving across the canvas for as long as possible. But i'm struggling to put a Timer to show your Time/Score when a ball hits the rectangle. (The rectangle is moved by the UP,DOWN,LEFT and RIGHT keys). Anyone with knowledge of this that could help me out would be much appreciated, thanks.
Here’s how to integrate a timer into your game:
Set the startingTime just before you start the game ticker:
/* Do the function, call every 20 milliseconds*/
startTime=new Date();
Draw the elapsed time whenever playGame is called:
/* MAIN GAME */
function playGame()
{
g.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas at start.
player.draw();
for (var i = 0; i < 8; i++)
{
ball[i].move();
ball[i].draw();
}
// draw the score
drawElapsedTime();
}
And finally, draw the final score when the game is over:
drawFinalScore();
alert("GAME OVER");
Also, I noticed you left the game ticker running even after the game ended. Here’s how to turn off the ticker:
// turn on the ticker and get a reference to the object
var theInterval=setInterval(playGame, 20);
// turn off the ticker
clearInterval(theInterval);
And…check out the new requestAnimationFrame ticker. It’s much more efficient and resource friendly than the older setInterval ticker. Here’s a link for requestAnimationFrame: http://paulirish.com/2011/requestanimationframe-for-smart-animating/
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/8qKht/
<!DOCTYPE html>
<html>
<head>
<style>
body
{
background-color:green;
}
#simpleCanvas
{
position: absolute;
top: 20%;
left: 30%;
border:2px solid blue;
width:500px;
height:500px;
background-color: yellow;
}
</style>
<script>
/* Ball Array */
var ball = new Array();
ball[0] = new Ball(150, 150); // x location of target, y location of target
ball[1] = new Ball(200, 350);
ball[2] = new Ball(400, 350);
ball[3] = new Ball(320, 250);
ball[4] = new Ball(440, 190);
ball[5] = new Ball(100, 350);
ball[6] = new Ball(80, 120);
ball[7] = new Ball(130, 240);
/* Player */
var player = new Player();
var score;
/* PLAYER OBJECT */
function Player()
{
/* private member variables */
var x = 10;
var y = 10;
var playerColour = "red";
var width = 25;
var height = 30;
var speed = 10;
/* public methods */
this.draw = draw;
function draw()
{
g.fillStyle = playerColour;
g.fillRect(x, y, width, height);
this.isHit();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getSpeed = getSpeed;
function getSpeed()
{
return speed;
}
this.getW = getW;
function getW()
{
return width;
}
this.getH = getH;
function getH()
{
return height;
}
this.isHit = isHit;
function isHit()
{
for (var i = 0; i < ball.length; i++)
{
if (((x + width) >= ball[i].getX()) && ((x + width) <= (ball[i].getX() + (ball[i].getRadius() * 2)))
&& ((y + height) >= ball[i].getY()) && ((y + height) <= (ball[i].getY() + (ball[i].getRadius() * 2))))
{
clearInterval(theInterval);
drawFinalScore();
//alert("GAME OVER");
console.log("game over");
}
}
}
}
/* BALL OBJECT */
function Ball(newX, newY)
{
var x = newX;
var y = newY;
var dx = 2;
var dy = 4;
var radius = 10;
var targetColour = "blue";
/* public methods */
this.draw = draw;
function draw()
{
g.beginPath();
g.fillStyle = targetColour;
g.arc(x, y, radius, 0, Math.PI * 2);
g.fill();
g.closePath();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getRadius = getRadius;
function getRadius()
{
return radius;
}
this.move = move;
function move()
{
x += dx;
y += dy;
// Bounce on a left or right edge.
if (x + dx > canvas.width - radius || x + dx < radius)
{
dx = -dx;
}
// If ball hits the top, bounce it.
else if (y + dy < radius)
{
dy = -dy;
}
//If the ball hits the bottom, check see if it hits a paddle.
else if (y + dy > canvas.height - radius)
{
dy = -dy;
}
}
}
/* MAIN GAME */
function playGame()
{
g.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas at start.
player.draw();
for (var i = 0; i < 8; i++)
{
ball[i].move();
ball[i].draw();
}
// draw the score
drawElapsedTime();
}
/* SCORE */
var startTime;
// ending elapsed time in seconds
var score;
function drawElapsedTime(){
var elapsed=parseInt((new Date() - startTime)/1000);
g.save();
g.beginPath();
g.fillStyle="red";
g.font="14px Verdana"
// draw the running time at half opacity
g.globalAlpha=0.50;
g.fillText(elapsed+" secs",canvas.width-75,25);
g.restore();
}
function drawFinalScore(){
// set the final score just once
if(score==null){ score=parseInt((new Date() - startTime)/1000); }
g.save();
g.beginPath();
g.fillStyle="red";
g.font="30px Verdana"
g.fillText("Game Over: "+score+" secs",50,35);
g.restore();
}
function arrowKeyDown(e)
{
var stepSize = 10; //Increase size
if (e.keyCode == 37) // left
{
player.setX(player.getX() - player.getSpeed());
if (player.getX() < 0)
{
player.setX(0);
}
}
else if(e.keyCode == 38) // up
{
player.setY(player.getY() - player.getSpeed());
if (player.getY() < 0)
{
player.setY(0);
}
}
else if(e.keyCode == 39) // right
{
player.setX(player.getX() + player.getSpeed());
if ((player.getX() + player.getW()) > canvas.width)
{
player.setX(canvas.width - player.getW());
}
}
else if(e.keyCode == 40) // down
{
player.setY(player.getY() + player.getSpeed());
if ((player.getY() + player.getH()) > canvas.height)
{
player.setY(canvas.height - player.getH());
}
}
}
document.addEventListener('keydown',arrowKeyDown);
</script>
</head>
<body>
<h1>A V O I D</h1>
<canvas id="simpleCanvas"></canvas>
<script>
/* Get the canvas id */
var canvas = document.getElementById("simpleCanvas");
/* Give the canvas a width and height */
/* The width and height are in canvas logical units */
canvas.width = 500;
canvas.height = 500;
/* Assign a graphics context to the canvas, so that we can draw on it */
var g = canvas.getContext("2d");
/* Do the function, call every 20 milliseconds*/
startTime=new Date();
var theInterval=setInterval(playGame, 20);
</script>
<audio src="intense.mp3" autoplay loop></audio>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<h1>
A V O I D
</h1>
<style>
body
{
background-color:green;
}
#simpleCanvas
{
position: absolute;
top: 20%;
left: 30%;
border:2px solid blue;
width:500px;
height:500px;
background-color: yellow;
}
}
</style>
<script>
/* Ball Array */
enter code here`var ball = new Array();
ball[0] = new Ball(150, 150); // x location of target, y location of target
ball[1] = new Ball(200, 350);
ball[2] = new Ball(400, 350);
ball[3] = new Ball(320, 250);
ball[4] = new Ball(440, 190);
ball[5] = new Ball(100, 350);
ball[6] = new Ball(80, 120);
ball[7] = new Ball(130, 240);
/* Player */
var player = new Player();
var score;
/* PLAYER OBJECT */
function Player()
{
/* private member variables */
var x = 10;
var y = 10;
var playerColour = "red";
var width = 25;
var height = 30;
var speed = 10;
/* public methods */
this.draw = draw;
function draw()
{
g.fillStyle = playerColour;
g.fillRect(x, y, width, height);
this.isHit();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getSpeed = getSpeed;
function getSpeed()
{
return speed;
}
this.getW = getW;
function getW()
{
return width;
}
this.getH = getH;
function getH()
{
return height;
}
this.isHit = isHit;
function isHit()
{
for (var i = 0; i < ball.length; i++)
{
if (((x + width) >= ball[i].getX()) && ((x + width) <= (ball[i].getX() + (ball[i].getRadius() * 2)))
&& ((y + height) >= ball[i].getY()) && ((y + height) <= (ball[i].getY() + (ball[i].getRadius() * 2))))
{
alert("GAME OVER");
}
}
}
}
/* BALL OBJECT */
function Ball(newX, newY)
{
var x = newX;
var y = newY;
var dx = 2;
var dy = 4;
var radius = 10;
var targetColour = "blue";
/* public methods */
this.draw = draw;
function draw()
{
g.beginPath();
g.fillStyle = targetColour;
g.arc(x, y, radius, 0, Math.PI * 2);
g.fill();
g.closePath();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getRadius = getRadius;
function getRadius()
{
return radius;
}
this.move = move;
function move()
{
x += dx;
y += dy;
// Bounce on a left or right edge.
if (x + dx > canvas.width - radius || x + dx < radius)
{
dx = -dx;
}
// If ball hits the top, bounce it.
else if (y + dy < radius)
{
dy = -dy;
}
//If the ball hits the bottom, check see if it hits a paddle.
else if (y + dy > canvas.height - radius)
{
dy = -dy;
}
}
}
/* MAIN GAME */
function playGame()
{
g.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas at start.
player.draw();
for (var i = 0; i < 8; i++)
{
ball[i].move();
ball[i].draw();
}
}
/* SCORE */
var isGameOver=false;
var startTime;
// ending elapsed time in seconds
var score;
function drawElapsedTime(){
var elapsed=parseInt((new Date() - startTime)/1000);
ctx.save();
ctx.beginPath();
ctx.fillStyle="red";
ctx.font="14px Verdana"
// draw the running time at half opacity
ctx.globalAlpha=0.50;
ctx.fillText(elapsed+" secs",canvas.width-75,25);
ctx.restore();
}
function drawFinalScore(){
// set the final score just once
if(score==null){ score=parseInt((new Date() - startTime)/1000); }
ctx.save();
ctx.beginPath();
ctx.fillStyle="red";
ctx.font="18px Verdana"
ctx.fillText("Game Over: "+score+" secs",20,25);
ctx.restore();
}
function arrowKeyDown(e)
{
var stepSize = 10; //Increase size
if (e.keyCode == 37) // left
{
player.setX(player.getX() - player.getSpeed());
if (player.getX() < 0)
{
player.setX(0);
}
}
else if(e.keyCode == 38) // up
{
player.setY(player.getY() - player.getSpeed());
if (player.getY() < 0)
{
player.setY(0);
}
}
else if(e.keyCode == 39) // right
{
player.setX(player.getX() + player.getSpeed());
if ((player.getX() + player.getW()) > canvas.width)
{
player.setX(canvas.width - player.getW());
}
}
else if(e.keyCode == 40) // down
{
player.setY(player.getY() + player.getSpeed());
if ((player.getY() + player.getH()) > canvas.height)
{
player.setY(canvas.height - player.getH());
}
}
}
document.addEventListener('keydown',arrowKeyDown);
</script>
</head>
<body>
<canvas id="simpleCanvas">
Your browser does not support the HTML5 <canvas> tag.
</canvas>
<script>
/* Get the canvas id */
var canvas = document.getElementById("simpleCanvas");
/* Give the canvas a width and height */
/* The width and height are in canvas logical units */
canvas.width = 500;
canvas.height = 500;
/* Assign a graphics context to the canvas, so that we can draw on it */
var g = canvas.getContext("2d");
/* Do the function, call every 20 milliseconds*/
setInterval(playGame, 20);
</script>
<audio src="intense.mp3" autoplay loop></audio>
</body>
</html>
/*This is my code and i tryed adding it in and making it function but it would not work ? Dont know what im doing wrong ? Thanks for the reply